解决golang 关于全局变量的坑


Posted in Golang onMay 06, 2021

学习golang不久,在定义全局变量的时候遇见了坑。写个小例子,增强记忆。

错误版本

var p int
func main() {
 p, err := test(4)
 if err != nil {
  log.Fatal(err)
 }
}
func test(i int) (int, error) {
 return i + 1, nil
}

编译一直不通过,p declared and not used。后来查了查资料,看见这种其实是在main里边又重新定义了p,所以一直提示p定义了但是没有使用。修改如下:

正确版本

var p int
func main() {
 var err error
 p, err = test(4)
 if err != nil {
  log.Fatal(err)
 }
}
func test(i int) (int, error) {
 return i + 1, nil
}

补充:golang变量作用域问题-避免使用全局变量

最近遇到了一个变量作用域的问题,一个比较低级的问题,可能作为一个熟手不应该犯这样的低级错误,但是golang的语法特点可能让你稍微不注意就踩坑,嘿嘿。

变量作用域

全局变量的作用域是整个包,局部变量的作用域是该变量所在的花括号内,这是一个很基础的问题。

我们通常会使用golang的一个语法糖:=来给变量赋值,这种方式可以节省掉我们定义变量的代码,让代码变的更加简洁,但是如果你定义了一个全局变量,又不小心用:=来给它赋值,就会出现一些问题。

问题

看下面的代码,定义了一个全局变量t,我想在init()中给他赋值为2,然后在main中使用它。

var t int
func init() {
    t, err := strconv.Atoi("2")
    if err != nil {
        log.Fatalln(err)
    }
    fmt.Println("init:", t)
}
func main() {
    fmt.Println("main:", t)
}

输出:

init: 2

main: 0

执行之后,在init和main中打印出了不一样的数字,为什么会不一样呢,可能你仔细一看就知道原因了。很简单,init中的t是用:=生成的,所以t是局部变量,在init函数中覆盖了全局变量t。全局变量t并没有被赋值,它还是原来的0值。

我本想在init中给全局变量t赋值的,却不小心用:=创建了一个局部变量导致全局变量t没有赋值成功,犯了一个低级错误。

解决

知道原因之后就容易解决了,我不使用:=就可以了。代码如下:

var t int
func init() {
    var err error
    t, err = strconv.Atoi("2")
    if err != nil {
        log.Fatalln(err)
    }
    fmt.Println("init:", t)
}
func main() {
    fmt.Println("main:", t)
}

输出:

init: 2

main: 2

没有使用:=之后,init中的t就是全局变量t,给全局变量t赋值为2,main中自然输出的就是2,实现了我最初的目的。

思考

这个问题很简单很低级,但是可能一个golang熟手,在代码远比demo要复杂的多的实际项目中,不经意间就可能会犯下这样的错误。

这个问题很难保证说下次一定不会出现的,除非你彻底不用全局变量或者彻底不用:=这样的语法糖。

我的建议是这样:

尽量少的使用全局变量。

尽量少的使用:=语法糖。

使用:=的时候要确保左值没有被定义过。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。如有错误或未考虑完全的地方,望不吝赐教。

Golang 相关文章推荐
golang正则之命名分组方式
Apr 25 Golang
go语言求任意类型切片的长度操作
Apr 26 Golang
Go语言切片前或中间插入项与内置copy()函数详解
Apr 27 Golang
解决Golang time.Parse和time.Format的时区问题
Apr 29 Golang
解决Go gorm踩过的坑
Apr 30 Golang
go web 预防跨站脚本的实现方式
Jun 11 Golang
golang中字符串MD5生成方式总结
Jul 04 Golang
Golang 链表的学习和使用
Apr 19 Golang
Golang 遍历二叉树
Apr 19 Golang
Golang获取List列表元素的四种方式
Apr 20 Golang
Golang日志包的使用
Apr 20 Golang
Golang 实现 WebSockets 之创建 WebSockets
Apr 24 Golang
Goland使用Go Modules创建/管理项目的操作
解决goland 导入项目后import里的包报红问题
Go 自定义package包设置与导入操作
goland 设置project gopath的操作
解决Goland 同一个package中函数互相调用的问题
浅谈golang package中init方法的多处定义及运行顺序问题
golang switch语句的灵活写法介绍
May 06 #Golang
You might like
Linux中为php配置伪静态
2014/12/17 PHP
浅析php设计模式之数据对象映射模式
2016/03/03 PHP
mysql desc(DESCRIBE)命令实例讲解
2016/09/24 PHP
PHP实现登陆表单提交CSRF及验证码
2017/01/24 PHP
PHP实现的简单排列组合算法应用示例
2017/06/20 PHP
laravel5环境隐藏index.php后缀(apache)的方法
2019/10/12 PHP
JS中Iframe之间传值的方法
2013/03/11 Javascript
解决Jquery鼠标经过不停滑动的问题
2014/03/03 Javascript
JavaScript截取指定长度字符串点击可以展开全部代码
2015/12/04 Javascript
jQuery过滤选择器经典应用
2016/08/18 Javascript
BootStrap框架中的data-[ ]自定义属性理解(推荐)
2017/02/14 Javascript
深入理解Node.js中的进程管理
2017/03/13 Javascript
关于Bootstrap按钮组件消除黄框的方法
2017/05/19 Javascript
浅谈react-router HashRouter和BrowserRouter的使用
2017/12/29 Javascript
解决jquery的ajax调取后端数据成功却渲染失败的问题
2018/08/08 jQuery
Layui Table js 模拟选中checkbox的例子
2019/09/03 Javascript
[03:44]2014DOTA2国际邀请赛 71专访:DK战队赛前讨论视频遭泄露
2014/07/13 DOTA
python中pycurl库的用法实例
2014/09/30 Python
简单介绍使用Python解析并修改XML文档的方法
2015/10/15 Python
python制作小说爬虫实录
2017/08/14 Python
Python使用装饰器进行django开发实例代码
2018/02/06 Python
特征脸(Eigenface)理论基础之PCA主成分分析法
2018/03/13 Python
对python中的 os.mkdir和os.mkdirs详解
2018/10/16 Python
简单了解python的一些位运算技巧
2019/07/13 Python
Python实现图像的垂直投影示例
2020/01/17 Python
pycharm实现print输出保存到txt文件
2020/06/01 Python
python3中数组逆序输出方法
2020/12/01 Python
MADE法国:提供原创设计师家具
2018/09/18 全球购物
绘画设计学生的个人自我评价
2013/09/20 职场文书
实习生岗位职责
2014/04/12 职场文书
本科毕业生自荐信
2014/05/26 职场文书
品质保证书格式
2015/02/28 职场文书
2015年度服装销售工作总结
2015/03/31 职场文书
2015年妇委会工作总结
2015/05/22 职场文书
观看禁毒宣传片后的感想
2015/08/11 职场文书
解析:创业计划书和商业计划书二者之间到底有什么区别
2019/08/14 职场文书