解决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判断key是否在map中的代码
Apr 24 Golang
golang在GRPC中设置client的超时时间
Apr 27 Golang
go语言中json数据的读取和写出操作
Apr 28 Golang
golang 如何通过反射创建新对象
Apr 28 Golang
golang 生成对应的数据表struct定义操作
Apr 28 Golang
Go 实现英尺和米的简单单位换算方式
Apr 29 Golang
golang DNS服务器的简单实现操作
Apr 30 Golang
go语言中GOPATH GOROOT的作用和设置方式
May 05 Golang
go开发alertmanger实现钉钉报警
Jul 16 Golang
如何利用golang运用mysql数据库
Mar 13 Golang
简单聊聊Golang中defer预计算参数
Mar 25 Golang
Golang 并发编程 SingleFlight模式
Apr 26 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初学者们头痛的十四个问题
2007/01/15 PHP
PHP下载远程文件到本地存储的方法
2015/03/24 PHP
CodeIgniter针对lighttpd服务器URL重写的方法
2015/06/10 PHP
yii2中使用Active Record模式的方法
2016/01/09 PHP
php利用gd库为图片添加水印
2016/11/09 PHP
实例讲解php实现多线程
2019/01/27 PHP
Laravel5.7框架安装与使用学习笔记图文详解
2019/04/02 PHP
Thinkphp5框架异常处理操作实例分析
2020/06/03 PHP
javascript实现二分查找法实现代码
2007/11/12 Javascript
Jquery 组合form元素为json格式,asp.net反序列化
2009/07/09 Javascript
jQuery列表拖动排列具体实现
2013/11/04 Javascript
在JavaScript的AngularJS库中进行单元测试的方法
2015/06/23 Javascript
jquery实现Li滚动时滚动条自动添加样式的方法
2015/08/10 Javascript
jQuery实现TAB选项卡切换特效简单演示
2016/03/04 Javascript
非常酷炫的Bootstrap图片轮播动画
2016/05/27 Javascript
使用vue.js实现checkbox的全选和多个的删除功能
2017/02/17 Javascript
详解如何实现一个简单的 vuex
2018/02/10 Javascript
react用Redux中央仓库实现一个todolist
2019/09/29 Javascript
微信小程序学习总结(五)常见问题实例小结
2020/06/04 Javascript
修改Vue打包后的默认文件名操作
2020/08/12 Javascript
python采集百度百科的方法
2015/06/05 Python
深入flask之异步非堵塞实现代码示例
2018/07/31 Python
python 字典中取值的两种方法小结
2018/08/02 Python
Django 中间键和上下文处理器的使用
2019/03/17 Python
详解python之heapq模块及排序操作
2019/04/04 Python
python scrapy爬虫代码及填坑
2019/08/12 Python
python opencv实现直线检测并测出倾斜角度(附源码+注释)
2020/12/31 Python
Jones New York官网:美国女装品牌,受白领女性欢迎
2019/11/26 全球购物
深圳茁壮笔试题
2015/05/28 面试题
环境科学专业大学生自荐信格式
2013/09/21 职场文书
银行领导证婚词
2014/01/11 职场文书
给国外客户的邀请函
2014/01/30 职场文书
合作意向书模板
2014/03/31 职场文书
《孙权劝学》教学反思
2014/04/23 职场文书
司机岗位职责说明书
2014/07/29 职场文书
异地恋情人节寄语
2015/02/28 职场文书