解决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 相关文章推荐
Go各时间字符串使用解析
Apr 02 Golang
Go语言-为什么返回值为接口类型,却返回结构体
Apr 24 Golang
golang如何去除多余空白字符(含制表符)
Apr 25 Golang
Go语言带缓冲的通道实现
Apr 26 Golang
Go语言中的UTF-8实现
Apr 26 Golang
goland 清除所有的默认设置操作
Apr 28 Golang
Golang: 内建容器的用法
May 05 Golang
Go语言grpc和protobuf
Apr 13 Golang
GO语言字符串处理函数之处理Strings包
Apr 14 Golang
Go中使用gjson来操作JSON数据的实现
Aug 14 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的session cookie错误
2009/08/09 PHP
PHP输入流php://input介绍
2012/09/18 PHP
详解YII关联查询
2016/01/10 PHP
PHP反射机制原理与用法详解
2017/02/15 PHP
基于jquery实现漂亮的动态信息提示效果
2011/08/02 Javascript
解决Extjs上传图片无法预览的解决方法
2012/03/22 Javascript
js onclick事件传参讲解
2013/11/06 Javascript
javascript实现仿IE顶部的可关闭警告条
2015/05/05 Javascript
JS实现光滑展开合拢的菜单效果代码
2015/09/16 Javascript
jQuery插件开发精品教程让你的jQuery提升一个台阶
2016/01/27 Javascript
javascript每日必学之条件分支
2016/02/17 Javascript
利用Query+bootstrap和js两种方式实现日期选择器
2017/01/10 Javascript
基于JavaScript实现购物车功能
2017/02/07 Javascript
webpack搭建vue 项目的步骤
2017/12/27 Javascript
vue-cli3.0 特性解读
2018/04/22 Javascript
使用ECharts实现状态区间图
2018/10/25 Javascript
jQuery实现模拟搜索引擎的智能提示功能简单示例
2019/01/27 jQuery
微信小程序前端自定义分享的实现方法
2019/06/13 Javascript
小程序分页实践之编写可复用分页组件
2019/07/18 Javascript
python益智游戏计算汉诺塔问题示例
2014/03/05 Python
用实例解释Python中的继承和多态的概念
2015/04/27 Python
python使用pipeline批量读写redis的方法
2019/02/18 Python
numpy concatenate数组拼接方法示例介绍
2019/05/27 Python
Python内存管理实例分析
2019/07/10 Python
详解Django中的FBV和CBV对比分析
2021/03/01 Python
video结合canvas实现视频在线截图功能
2018/06/25 HTML / CSS
英国时尚服饰电商:Boohoo
2017/10/12 全球购物
一份Java笔试题
2012/02/21 面试题
机电工程学生自荐信范文
2013/12/07 职场文书
文员的职业生涯规划发展方向
2014/02/08 职场文书
浪费资源的建议书
2014/03/12 职场文书
学员自我鉴定
2014/03/19 职场文书
计划生育标语
2014/06/23 职场文书
高中生旷课检讨书
2014/10/08 职场文书
工作经验交流材料
2014/12/30 职场文书
2016年学校“3.12”植树节活动总结
2016/03/16 职场文书