解决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:垃圾回收GC触发条件详解
Apr 24 Golang
Go语言带缓冲的通道实现
Apr 26 Golang
Golang 实现超大文件读取的两种方法
Apr 27 Golang
golang 实现对Map进行键值自定义排序
Apr 28 Golang
golang elasticsearch Client的使用详解
May 05 Golang
go语言中fallthrough的用法说明
May 06 Golang
golang中字符串MD5生成方式总结
Jul 04 Golang
深入理解go slice结构
Sep 15 Golang
golang实现一个简单的websocket聊天室功能
Oct 05 Golang
Go归并排序算法的实现方法
Apr 06 Golang
golang操作redis的客户端包有多个比如redigo、go-redis
Apr 14 Golang
Go调用Rust方法及外部函数接口前置
Jun 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 魔术方法使用说明
2009/10/20 PHP
JavaScript 不只是脚本
2007/05/30 Javascript
jquery 图片 上一张 下一张 链接效果(续篇)
2010/04/20 Javascript
js 图片等比例缩放代码
2010/05/13 Javascript
JS控件的生命周期介绍
2012/10/22 Javascript
浅析JQuery UI Dialog的样式设置问题
2013/12/18 Javascript
jQuery实现的导航条切换可显示隐藏
2014/10/22 Javascript
jQuery实现的右下角广告窗体跟随效果示例
2016/09/16 Javascript
在node.js中怎么屏蔽掉favicon.ico的请求
2017/03/01 Javascript
JS实现数组去重方法总结(六种方法)
2017/07/14 Javascript
解决jquery的ajax调取后端数据成功却渲染失败的问题
2018/08/08 jQuery
layui的table中显示图片方法
2018/08/17 Javascript
layui监听select变化,以及设置radio选中的方法
2019/09/24 Javascript
Egg Vue SSR 服务端渲染数据请求与asyncData
2019/11/24 Javascript
通过高德地图API获得某条道路上的所有坐标用于描绘道路的方法
2020/08/24 Javascript
[06:33]3.19 DOTA2发布会 海涛、冷冷、2009见证希望
2014/03/21 DOTA
跟老齐学Python之玩转字符串(2)
2014/09/14 Python
Python编程中的反模式实例分析
2014/12/08 Python
python实现带验证码网站的自动登陆实现代码
2015/01/12 Python
Python可变和不可变、类的私有属性实例分析
2019/05/31 Python
利用selenium爬虫抓取数据的基础教程
2019/06/10 Python
python实现H2O中的随机森林算法介绍及其项目实战
2019/08/29 Python
Python字典中的值为列表或字典的构造实例
2019/12/16 Python
IronPython连接MySQL的方法步骤
2019/12/27 Python
Tensorflow矩阵运算实例(矩阵相乘,点乘,行/列累加)
2020/02/05 Python
对CSS3选择器的研究(详解)
2016/09/16 HTML / CSS
台湾最大银发乐活百货:乐龄网
2018/05/21 全球购物
如何利用XMLHTTP检测URL及探测服务器信息
2013/11/10 面试题
乔布斯斯坦福大学演讲稿
2014/05/23 职场文书
公司任命书模板
2014/06/06 职场文书
银行党的群众路线教育实践活动对照检查材料
2014/09/25 职场文书
岗位竞聘报告范文
2014/11/06 职场文书
起诉离婚协议书样本
2014/11/25 职场文书
中学推普周活动总结
2015/05/07 职场文书
安全学习心得体会范文
2016/01/18 职场文书
pytest配置文件pytest.ini的详细使用
2021/04/17 Python