一个因全局变量引发的故事!

我是阿沐
• 阅读 1756

前言

科比问道:“你知道洛杉矶每天早上四点钟是什么样子嘛?”,我没见过,但是我经常见广州白云区四点钟的样子。

是不是在早晨阳光下看着跟随自己前行的身影道:“起的比鸡早,睡的比狗晚,或许这是我最后一次努力的挣扎”。

睡梦惊醒

我有一个中午空出半个小时看书的习惯,那天中午看到1点钟的时候,确实有点困了,就急忙合上书躺椅子上睡一觉,正在做梦呢!突然一把被同事(妹子)推醒了:“快快快,起来帮我看看,出问题了!”

我睁开眼看着同事已经急的满头大汗,紧紧张张望着我,仿佛在抓着一棵救命稻草;有点眼泪汪汪的样子。

“火急火燎的,咋啦这是?地震了吗?”

“wocao(估计急很了),不是不是,线上活动出问题了,快帮我看看,我看了几遍了,找不到问题。”

“啥活动啊,我咋不知道?”

“就是前两天运营给的一个520情人节活动。”

“哦哦,现在线上具体出现什么问题?”

“线上用户每天排行榜发道具礼物,出现部分人的名次按照第一名的奖励发放了。”

“不是吧?影响了多少用户了?”

10000个用户了。”

一脸懵逼。我当时内心是有点奔溃的,这影响人数加上道具是有价值(rmb),岂不是会被上报通告,扣分。忽然间想起来了多年前刚刚踏入程序员行业,因为做活动code review代码没看到问题,导致损失3w+并且被客户投诉,当时被老板,运营经理,测试经理各种diss(公司通报);当晚一个人站在外滩的一个角落里:偷偷抹眼泪,还被别人偷拍。外滩冷风,也冷透了我的心。

“代码在哪个分支,发给我我拉代码看看下?是不是没有给我review代码?”

feature/#87656-Valentine-Day,是这个分支,企业微信很快发给我了。”

我看着她那无助的眼神,现在变成有了依靠一般。

“别着急,我看看代码先!”

我大概看了几分钟(1000多行代码),基本上已经确定了问题。估计她是看到我停下翻滚代码了,气氛也缓和了不少。

“你是不是没有看到lua规范wiki文档?不知道禁止使用全局变量嘛?”

“啥?我有使用全局变量嘛?我不知道啊,我没用啊,不是一样的嘛?”

看着慌张的解释,我欲言又止。是该怎样心平气和的跟她讲自己的细节处理问题,犯了很低级的问题,本可以避免但是犯的错误。

“你头伸过来看看这里,这里和这里,是不是,你在全局设置了道具全局变量,但是下面查询的时候有把变量值变更了,导致第一名以外的用户都拿到了第一名的奖励;全局数据被污染了”

lua语言中的全局变量和局部变量有具体了解过嘛?全局变量:顾名思义,生命周期是全局,整个lua文件都可以访问使用,设置完全局变量就可以在 _G表 通过 table表 访问;存在 污染文件 的变量,维护起来很麻烦。局部变量:只在某些特定的 范围内 有效的变量,称为局部变量,用local修饰;所以平常为了方便维护,尽量使用局部变量。

“哦哦,原来如此,我是看别人代码也会这样写,所以就照抄了,谁知道发生这种事情。”

你作为一个两年后端开发,不能只会ctrl+c + ctrl+v,要清楚别人为什么这么写?文档也要看的哦,我像是一个大哥在教育小妹妹(96)。

“我也不想啊,这不是刚刚从java语言转lua语言吗?哪里知道这么多?”

气死😤 我了,这不是成心气我嘛!文档给你了,注意事项也写了,而且还红色标注:“重要的事情说三遍

“修改下这几个地方,提交测试环境,找测试再次过下,这种必现的问题,没测试出来!后面需要 复盘 这次的问题”

“哦!”

再次一脸懵逼:这前后态度转变也太大了,现在的 小姑娘 都这么豪横了嘛?带我这新同事真的要把我累死。还好是个漂亮妹纸,不然我就要生气的教导了,实在是咱们这行漂亮的后端妹纸太少见了。整个组就这几个妹纸,就属她最 ,肯定是 大熊猫级别 的保护了。

“咋啦,咋啦,不懂还不能问问啦,谁叫我这么菜呢?下午请你喝下午茶啦”

就是这么豪横,我这不能忍了! 但是听到有下午茶喝:“没事,没事,等下改完上线,我再跟你详细说下全局变量和局部变量使用”!

傍晚黄昏

临近下班了,正在聚精会神的思考问题,回顾今天做了什么事情,还有什么事情没有做完,安排下明天的工作!突然耳边出现:

“忙完了吗?我想请教你下中午的那个bug问题?”

“你不要突然袭出现,吓了我一大跳,正在想事情呢?”

大部分的程序员都对自己写的代码非常的自信甚至自负,经常可以在耳边听到:“卧槽,不可能啊,我明明测试过了,不会出错啊,你重启下或者你再试一试?”,实际上已经偷偷自己跑测试环境去看了,赶紧修好。然后再跟测试说:“我这边确实没问题,你再看下!”。测试一看:“难道我看错了。就回复到,没问题了”

“平常跟你说多看 wiki文档,上面的组织架构图,redis集群mysql机器中间件异地多活等等,甚至是平常遇到的坑上面都会有,你要主动去看去学习!”

“走走走,咱们带着电脑去个小会议室聊一聊!”

神经兮兮:非要这么搞嘛?直接找个椅子坐旁边聊就好啦,这让别人看到怎么办?会不会被误解,我对她有想法?在这个虎视眈眈的大集体中,有多少双眼睛在盯着她,不经后背抖了一下。

“不要把气氛弄得这么紧张,搞得我很不适应呀!”

“简简单单的聊聊,找个人少的地方问问题,别等下大家听到了,又说我菜的抠脚!”

那你现在知道lua语言中基本不建议使用全局变量,而让使用局部变量嘛?

“不知道,你跟我讲讲呗!”

## 那你要记住了,我再仔细的跟你讲一遍,下次不能犯这样的低级错误

## 不建议使用 全局变量主要有两个原因:

① 为了避免因设置全局变量出现命名冲突,使得污染整个项目,所以尽量使用局部变量

② 访问局部变量的速度比全局变量更快

“那你说说下为啥会影响到其他文件吗?”

print("*********************我是全局变量**************************")
global_variable = function ( ... )
    name = "我是阿沐"
end
global_variable() -- 调用函数
print(name)

print("*********************我是局部变量**************************")

local_variable = function ( ... )
    local age = 26
end
local_variable() -- 调用函数
print(age)

print("*********************清除全局变量值**************************")
_G.name = nil
print(name)

”看下上面结果会是神马?“

”肯定是 我是阿沐, 26, 我是阿沐啦!“

我差点被你气出心脏病来了,看看下面的结果集。

*********************我是全局变量**************************
我是阿沐

*********************我是局部变量**************************
nil

nil

一个因全局变量引发的故事!

”这么神奇嘛?怎么最后 全局变量 怎么没有值了?“

”你想知道原因嘛?“

”想想想,赶紧告诉我呗,有点意思“

其实我们声明的全局变量都会存储在大G表,_G是一张表,保存了lua所用的所有全局函数全局变量,我们可以像访问table一样访问_G中的值

print("*********************_G表**************************")
-- 先设置一个局部变量 为了验证_G只存储全局变量和全局函数
local sex = 1
-- 大G表是一个table 且是键值对这种 所以使用pairs
for i,v in pairs(_G) do
    print(i,v)
end

看下执行结果

*********************_G表**************************
name            我是阿沐   -- 这个不就是刚刚我们设置的全局变量嘛
table           table: 0x7faba8c036b0
dofile          function: 0x1007b697d
assert          function: 0x1007b684e
_G              table: 0x7faba8c02770
string          table: 0x7faba8c04fc0
io              table: 0x7faba8c04260
ipairs          function: 0x1007b6aa8
tostring        function: 0x1007b72a8
........        .....................
debug           table: 0x7faba8c04b80
require         function: 0x7faba8c03d30

”哦哦,原来如此,我知道为什么我上午那个活动出现这个问题了,是因为我在文件头部声明了全局变量,并且在别的方法给修改了,导致我再次拿到的值就变化了!“

”你是真的聪明,‘一点击破’ 🙄 ,我我我,真的太难了。“

”咋,你就不能把我当做lua语言的小白教导一下?何况我还是妹纸,难道你就没有一点怜香惜玉的气度?哼~

”行行行,可以教你!现在明白了,可以下班回去了吧?“

”等等,我还有一个疑问,你不是说访问局部变量比全局变量快嘛?这个怎么理解?🤔 “

”你这是不想让我下班啊,我还想回去做个毛血旺吃呢!,得得得,跟你说下,谁叫你是全组最靓的仔“

”我是全组最靓的靓女,不是仔! “

① lua在5.0版本之后,它使用了一种类似寄存器的虚拟模式;② lua用来存储其寄存器。每一个函数lua都会对其分配一个栈,存储函数中的活动数据;③ lua的编译器将local变量存储至寄存器,对local变量的操作就相当于直接对寄存器进行操作,对global变量的操作要先获取变量,然后才能对其进一步操作,自然局部变量比全局变量快。要知道内存访问速度是没有寄存器快的,而lua的全局变量又是通过 table 访问,相当于中间又多了一层间接访问,肯定要比局部变量慢很多啦

”我已经有点晕了,能不能举个例子证明下,讲一堆概念不如一个案例来的实在,嘻嘻 😬 。“

print("*********************全局变量和局部变量访问速度**************************")

### 全局变量
sum = 0 -- 声明一个全局变量值
for i=1,100000 do
  sum = sum + i
end

print(sum)
print(os.clock()) -- 返回一个程序使用CPU时间的一个近似值

### 局部变量
local sum = 0  -- 声明一个局部变量值
for i=1, 100000 do
  sum = sum + i
end
print(sum)
print(os.clock())

### 执行结果集

➜~ lua hello.lua
*********************全局变量和局部变量访问速度**************************
5000050000
0.006693

5000050000
0.00768

”仔细看看上面两个执行的时间,有什么不一样嘛?“

”哇塞!这两个结果差距这么大啊,全局变量访问比局部访问慢了好多!明白了,明白了~~“

”我再跟你强调下 lua 中使用全局变量的缺点!“

  • 因为是全局,声明变量名称容易冲突,项目有多人维护,不可能每次都能避免
  • 访问全局变量的速度比局部变量的速度慢 平常写代码中要细心一点,不能马大哈!多要想想为什么别人这样写没问题,你复制粘贴之后就出问题了?学会惯性思考,更重要一点提交代码走测试流程之前 一定要 找我 code review

”好的,老板!我知道了,以后学习中还要你多多指导呀!明天下午请你喝星巴克

”哦哦,我可以下班了吗?“

”走呀,走呀,腿长在你身上,我又没有拉着不放你走!走吧,该下班了,都已经8点半了!“

一起走出园区,看着互相离去的背影;似乎看到了当年初出茅庐的我,也是经不起打击、经不住上级给的压力;仰望星空,告诉自己:”我们虽然已经走过了最难煎熬的一段历程,但不代表我们可以放松;落后就要挨打,亘古不变的道理!“

当我们走投无路的时候:”努力,或许是你最后的救命稻草!“。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Android蓝牙连接汽车OBD设备
//设备连接public class BluetoothConnect implements Runnable {    private static final UUID CONNECT_UUID  UUID.fromString("0000110100001000800000805F9B34FB");
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
我是阿沐
我是阿沐
Lv1
男 · 腾讯音乐后端开发工程师 | 微信搜:我是阿沐
思绪来得快去得也快,偶尔会在这里停留
文章
15
粉丝
3
获赞
5