解决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
golang 如何用反射reflect操作结构体
Apr 28 Golang
go类型转换及与C的类型转换方式
May 05 Golang
Go遍历struct,map,slice的实现
Jun 13 Golang
手把手教你导入Go语言第三方库
Aug 04 Golang
golang生成vcf通讯录格式文件详情
Mar 25 Golang
Golang jwt身份认证
Apr 20 Golang
Golang 切片(Slice)实现增删改查
Apr 22 Golang
GoFrame框架数据校验之校验结果Error接口对象
Jun 21 Golang
GO中sync包自由控制并发示例详解
Aug 05 Golang
Goland使用Go Modules创建/管理项目的操作
解决goland 导入项目后import里的包报红问题
Go 自定义package包设置与导入操作
goland 设置project gopath的操作
解决Goland 同一个package中函数互相调用的问题
浅谈golang package中init方法的多处定义及运行顺序问题
golang switch语句的灵活写法介绍
May 06 #Golang
You might like
php中利用explode函数分割字符串到数组
2014/02/08 PHP
XML+XSL 与 HTML 两种方案的结合
2007/04/22 Javascript
直接生成打开窗口代码,不必下载
2008/05/14 Javascript
javascript 进阶篇2 CSS XML学习
2012/03/14 Javascript
Iframe实现跨浏览器自适应高度解决方法
2014/09/02 Javascript
JavaScript前补零操作实例
2015/03/11 Javascript
学习JavaScript设计模式之迭代器模式
2016/01/19 Javascript
jQuery form插件之ajaxForm()和ajaxSubmit()的可选参数项对象
2016/01/23 Javascript
教你用javascript实现随机标签云效果_附代码
2016/03/16 Javascript
15个值得开发人员关注的jQuery开发技巧和心得总结【经典收藏】
2016/05/25 Javascript
AngularJS基础 ng-href 指令用法
2016/08/01 Javascript
bootstrap日历插件datetimepicker使用方法
2016/12/14 Javascript
ES6学习教程之Map的常用方法总结
2017/08/03 Javascript
JS 中LocalStorage和SessionStorage的使用
2017/08/17 Javascript
快速理解 JavaScript 中的 LHS 和 RHS 查询的用法
2017/08/24 Javascript
关于jquery中attr()和prop()方法的区别
2018/05/28 jQuery
vue打包使用Nginx代理解决跨域问题
2018/08/27 Javascript
Swiper.js实现移动端元素左右滑动
2019/09/08 Javascript
JS实现移动端可折叠导航菜单(现代都市风)
2020/07/07 Javascript
[03:10]2014DOTA2 TI马来劲旅Titan首战告捷目标只是8强
2014/07/10 DOTA
[52:03]DOTA2-DPC中国联赛 正赛 Ehome vs iG BO3 第三场 1月31日
2021/03/11 DOTA
Python中字符串的修改及传参详解
2016/11/30 Python
python将ansible配置转为json格式实例代码
2017/05/15 Python
PyTorch上搭建简单神经网络实现回归和分类的示例
2018/04/28 Python
利用pyinstaller打包exe文件的基本教程
2019/05/02 Python
tensorflow对图像进行拼接的例子
2020/02/05 Python
使用Pyhton 分析酒店针孔摄像头
2020/03/04 Python
Python内置函数property()如何使用
2020/09/01 Python
调用HTML5的Canvas API绘制图形的快速入门指南
2016/06/17 HTML / CSS
德国滑雪和户外用品网上商店:XSPO
2019/10/30 全球购物
《骆驼和羊》教学反思
2014/02/27 职场文书
2014学雷锋活动总结
2014/03/09 职场文书
优秀少先队员主要事迹材料
2014/05/28 职场文书
学生党员批评与自我批评
2014/10/15 职场文书
基于Pygame实现简单的贪吃蛇游戏
2021/12/06 Python
Python绘制散乱的点构成的图的方法
2022/04/21 Python