解决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语言中的UTF-8实现
Apr 26 Golang
解决go在函数退出后子协程的退出问题
Apr 30 Golang
解决Golang中goroutine执行速度的问题
May 02 Golang
浅谈golang package中init方法的多处定义及运行顺序问题
May 06 Golang
go 实现简易端口扫描的示例
May 22 Golang
Go 语言结构实例分析
Jul 04 Golang
Go Plugins插件的实现方式
Aug 07 Golang
Golang表示枚举类型的详细讲解
Sep 04 Golang
golang操作redis的客户端包有多个比如redigo、go-redis
Apr 14 Golang
Go语言入门exec的基本使用
May 20 Golang
Go语言编译原理之源码调试
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
新版mysql+apache+php Linux安装指南
2006/10/09 PHP
sourcesafe管理phpproj文件的补充说明(downmoon)
2009/04/11 PHP
PHP高自定义性安全验证码代码
2011/11/27 PHP
php5.3不能连接mssql数据库的解决方法
2014/12/27 PHP
关于Yii2框架跑脚本时内存泄漏问题的分析与解决
2019/12/01 PHP
理解JavaScript中的事件
2006/09/23 Javascript
可以支持多中格式的JS键盘
2007/05/02 Javascript
让iframe子窗体取父窗体地址栏参数(querystring)
2009/10/13 Javascript
document.body.scrollTop 值总为0的解决方法 比较常见的标准问题
2009/11/30 Javascript
Javascript页面添加到收藏夹的简单方法
2013/08/07 Javascript
jQuery中nextAll()方法用法实例
2015/01/07 Javascript
Javascript控制input输入时间格式的方法
2015/01/28 Javascript
js实现滑动触屏事件监听的方法
2015/05/05 Javascript
JS、jQuery中select的用法详解
2016/04/21 Javascript
全面介绍javascript实用技巧及单竖杠
2016/07/18 Javascript
jQuery Ajax实现跨域请求
2017/01/21 Javascript
微信小程序商城项目之淘宝分类入口(2)
2017/04/17 Javascript
Angular将填入表单的数据渲染到表格的方法
2017/09/22 Javascript
Element Table的row-class-name无效与动态高亮显示选中行背景色
2018/11/30 Javascript
微信小程序语音同步智能识别的实现案例代码解析
2020/05/29 Javascript
解决vscode进行vue格式化,会自动补分号和双引号的问题
2020/10/26 Javascript
Python中处理字符串之endswith()方法的使用简介
2015/05/18 Python
在Python 中实现图片加框和加字的方法
2019/01/26 Python
Python序列化pickle模块使用详解
2020/03/05 Python
Python作用域与名字空间原理详解
2020/03/21 Python
Python可以实现栈的结构吗
2020/05/27 Python
Nike加拿大官网:Nike.com (CA)
2019/04/09 全球购物
美国体育用品商店:Academy Sports + Outdoors
2020/01/04 全球购物
extern是什么意思
2016/03/10 面试题
毕业生求职自荐书范文
2014/03/27 职场文书
租房协议书怎么写
2014/04/10 职场文书
完整版商业计划书
2014/09/15 职场文书
先进个人材料怎么写
2014/12/30 职场文书
应急管理工作总结2015
2015/05/04 职场文书
python实现高效的遗传算法
2021/04/07 Python
vue如何使用模拟的json数据查看效果
2022/03/31 Vue.js