解决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二维切片初始化的实现
Apr 08 Golang
Golang 空map和未初始化map的注意事项说明
Apr 29 Golang
golang日志包logger的用法详解
May 05 Golang
Golang实现AES对称加密的过程详解
May 20 Golang
golang为什么要统一错误处理
Apr 03 Golang
Go语言的协程上下文的几个方法和用法
Apr 11 Golang
Golang流模式之grpc的四种数据流
Apr 13 Golang
Golang ort 中的sortInts 方法
Apr 24 Golang
Golang入门之计时器
May 04 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
松下Panasonic RF-B65电路分析
2021/03/02 无线电
PHP实现图片裁剪、添加水印效果代码
2014/10/01 PHP
Yii隐藏URL中index.php的方法
2016/07/12 PHP
Yii2.0表关联查询实例分析
2016/07/18 PHP
php+ajax实现无刷新文件上传功能(ajaxuploadfile)
2018/02/11 PHP
Jquery实现点击切换图片并隐藏显示内容(2种方法实现)
2013/04/11 Javascript
js图片延迟加载的实现方法及思路
2013/07/22 Javascript
jQuery实现的多选框多级联动插件
2014/05/02 Javascript
在ASP.NET MVC项目中使用RequireJS库的用法示例
2016/02/15 Javascript
DeviceOne 让你一见钟情的App快速开发平台
2016/02/17 Javascript
AngularJS通过$http和服务器通信详解
2016/09/21 Javascript
javascript 取小数点后几位几种方法总结
2017/08/02 Javascript
js如何找出字符串中的最长回文串
2018/06/04 Javascript
微信小程序实现简单评论功能
2018/11/28 Javascript
如何在Vue.js中实现标签页组件详解
2019/01/02 Javascript
vue proxy 的优势与使用场景实现
2020/06/15 Javascript
Ant Design Pro 之 ProTable使用操作
2020/10/31 Javascript
[01:08:44]NB vs VP 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
Python3.4编程实现简单抓取爬虫功能示例
2017/09/14 Python
python利用sklearn包编写决策树源代码
2017/12/21 Python
python去除文件中重复的行实例
2018/06/29 Python
Linux下python3.6.1环境配置教程
2018/09/26 Python
python 日期排序的实例代码
2019/07/11 Python
Python selenium使用autoIT上传附件过程详解
2020/05/26 Python
Python文件夹批处理操作代码实例
2020/07/21 Python
Python下载网易云歌单歌曲的示例代码
2020/08/12 Python
css3实现背景颜色渐变让图片不再是唯一的实现方式
2012/12/18 HTML / CSS
细说CSS3中box属性中的overflow-x属性和overflow-y属性值的效果
2014/07/21 HTML / CSS
英国汽车座椅和婴儿车购物网站:Uber Kids
2017/04/19 全球购物
生物科学专业个人求职信范文
2013/12/05 职场文书
妈妈的账单教学反思
2014/02/06 职场文书
大学自主招生推荐信
2014/05/10 职场文书
2014年群众路线党员自我评议
2014/09/24 职场文书
面试通知单大全
2015/04/20 职场文书
党内外群众意见范文
2015/06/02 职场文书
利用前端HTML+CSS+JS开发简单的TODOLIST功能(记事本)
2021/04/13 Javascript