解决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 相关文章推荐
goland 恢复已更改文件的操作
Apr 28 Golang
Golang 编译成DLL文件的操作
May 06 Golang
goland 设置project gopath的操作
May 06 Golang
go xorm框架的使用
May 22 Golang
浅谈Go语言多态的实现与interface使用
Jun 16 Golang
入门学习Go的基本语法
Jul 07 Golang
Go语言基础函数基本用法及示例详解
Nov 17 Golang
Go语言基础map用法及示例详解
Nov 17 Golang
Go并发4种方法简明讲解
Apr 06 Golang
golang三种设计模式之简单工厂、方法工厂和抽象工厂
Apr 10 Golang
Go Grpc Gateway兼容HTTP协议文档自动生成网关
Jun 16 Golang
在ubuntu下安装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
咖啡冲泡指南 咖啡有哪些制作方式 单品咖啡 意式咖啡
2021/03/06 冲泡冲煮
PHP编程之高级技巧——利用Mysql函数
2006/10/09 PHP
Ajax+PHP快速上手及简单应用说明
2013/07/24 PHP
PHP字符串比较函数strcmp()和strcasecmp()使用总结
2014/11/19 PHP
php基于Redis消息队列实现的消息推送的方法
2018/11/28 PHP
PHP智能识别收货地址信息实例
2019/01/05 PHP
JavaScript脚本性能优化注意事项
2008/11/18 Javascript
基于jQuery的图片左右无缝滚动插件
2012/05/23 Javascript
jQuery图片轮播的具体实现
2013/09/11 Javascript
JS判断变量是否为空判断是否null
2014/07/25 Javascript
jQuery中prevUntil()方法用法实例
2015/01/08 Javascript
js实现点击按钮后给Div图层设置随机背景颜色的方法
2015/05/06 Javascript
Jquery效果大全之制作电脑健康体检得分特效附源码下载
2015/11/02 Javascript
js带闹铃功能的倒计时代码
2016/09/29 Javascript
JS 实现可停顿的垂直滚动实例代码
2016/11/23 Javascript
jQuery中on方法使用注意事项详解
2017/02/15 Javascript
async/await地狱该如何避免详解
2018/05/10 Javascript
微信小程序实现多个按钮的颜色状态转换
2019/02/15 Javascript
如何在Angular8.0下使用ngx-translate进行国际化配置
2019/07/24 Javascript
解决vue-cli输入命令vue ui没效果的问题
2020/11/17 Javascript
[52:36]VGJ.S vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
Python AES加密模块用法分析
2017/05/22 Python
python GUI实例学习
2017/11/21 Python
python自动12306抢票软件实现代码
2018/02/24 Python
浅谈pytorch grad_fn以及权重梯度不更新的问题
2019/08/20 Python
使用python turtle画高达
2020/01/19 Python
python3中sys.argv的实例用法
2020/04/24 Python
Python多线程:主线程等待所有子线程结束代码
2020/04/25 Python
HTML5语义化元素你真的用对了吗
2019/08/22 HTML / CSS
Omio葡萄牙:全欧洲低价大巴、火车和航班搜索和比价
2019/02/09 全球购物
Steiff台湾官网:德国金耳釦泰迪熊
2019/12/26 全球购物
自动化毕业生专业自荐书范文
2014/02/04 职场文书
实验教师岗位职责
2014/02/13 职场文书
新婚姻法离婚协议书范文
2014/11/30 职场文书
2014教师专业技术工作总结
2014/12/03 职场文书
Python Django搭建文件下载服务器的实现
2021/05/10 Python