最近遇到了一个变量作用域的问题,一个比较低级的问题,可能作为一个熟手不应该犯这样的低级错误,但是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变量作用域问题-避免使用全局变量的更多相关文章

  1. 一个有关Golang变量作用域的坑

    转自:http://tonybai.com/2015/01/13/a-hole-about-variable-scope-in-golang/ 临近下班前编写和调试一段Golang代码,但运行结果始终 ...

  2. C/C++语言中变量作用域:局部变量,全局变量,文件级变量

    C/C++语言中的变量分为全局变量和局部变量. 这样的划分方式的根据是变量的可见范围或者叫做作用域. 1 局部变量 局部变量指的是定义在{}中的变量,其作用域也在这个范围内.尽管常见的局部变量都是定义 ...

  3. python基础----函数的定义和调用、return语句、变量作用域、传参、函数嵌套、函数对象、闭包、递归函数

    1.函数的定义: 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也可 ...

  4. golang变量

    一.变量的概念 变量是程序的基本组成单位.变量表示内存中的一个存储区域,该区域有自己的名称(变量名)和类型(数据类型).变量相当于内存中一个数据存储空间的表示,你可以把变量看做是一个房间的门 牌号,通 ...

  5. Python-变量、变量作用域、垃圾回收机制原理-global nonlocal

    变量实现原理决定了Python使用的垃圾回收机制为变量引用计数,当这个对象引用计数为0时候,则会自动执行__del__函数回收资源, del方法只是把变量指向的对象引用计数减一而已并删除这个变量 表达 ...

  6. javascript中的变量作用域以及变量提升

    在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解. 变量作用域 “一个变量的作用域表示这个变量存在的上 ...

  7. [转]深入理解JavaScript的变量作用域

    1.JavaScript的作用域链 2.函数体内部,局部变量的优先级比同名的全局变量高. 3.JavaScript没有块级作用域. 4.函数中声明的变量在整个函数中都有定义. 5.未使用var关键字定 ...

  8. PHP常量、变量作用域详解(一)

    PHP 中的每个变量都有一个针对它的作用域,它是指可以在其中访问变量(从而访问它的值)的一个领域.对于初学者来说,变量的作用域是它们所驻留的页面.因此, 如果你定义了 $var,页面余下部分就可以访问 ...

  9. PHP变量作用域详解(二)

    学过C的人用PHP的时候一般会相当顺手,而且感到PHP太方便太轻松.但在变量作用域这方面却与C有不同的地方,搞不好会相当郁闷,就找不到错误所在.昨晚就与到这么一个问题,是全局变量在函数中的问题.今天搜 ...

随机推荐

  1. Coursera课程 Programming Languages, Part C 总结

    碎言碎语 和前面的 ML 和 Racket 感觉明显不一样了,一边学着一边觉得这真是一门奇怪的语言,有着各种奇怪的语法,不过真的算是一个奇妙的体验(相比前面的两门语言,Ruby 的学习资源多了不少). ...

  2. JavaScript基础知识(JSON、Function对象、原型、引用类型)

    19.JSON 概念:JavaScript 对象表示法(JavaScript Object Notation),是一种轻量级的数据交换格式  特点:易于程序员编写和查看:易于计算机解析和生成 数据结构 ...

  3. Java与算法之(9) - 直接插入排序

    直接插入排序是最简单的排序算法,也比较符合人的思维习惯.想像一下玩扑克牌抓牌的过程.第一张抓到5,放在手里:第二张抓到3,习惯性的会把它放在5的前面:第三张抓到7,放在5的后面:第四张抓到4,那么我们 ...

  4. JavaScript正则表达式验证大全(收集)

    以下函数调用方式: ? 1 2 3 4 function check() { var bb = document.getElementById("txt_id").value;// ...

  5. C/C++中substr函数的应用(简单讲解)

    substr(字符串,截取开始位置,截取长度) //返回截取的字 substr('Hello World',0,1) //返回结果为 'H'  *从字符串第一个字符开始截取长度为1的字符串 subst ...

  6. 在R12下加载Java Bean,配置FORMS_WEB_CONFIG_FILE文件/通过AutoConfig实现Form Server配置文件的修改

    1.定位模版文件$AD_TOP/bin/adtmplreport.sh contextfile=$CONTEXT_FILE target=$FORMS_WEB_CONFIG_FILE以上命令,通过查看 ...

  7. oracle 11g体系结构

    1.数据库体系结构 1.1 数据库和实例的关系database server  = instance 实例 + database 数据库instance 实例  =内存 memory + 进程  pr ...

  8. typedef和define具体的详细区别

    1) #define是预处理指令,在编译预处理时进行简单的替换,不作正确性检查,不关含义是否正确照样带入,只有在编译已被展开的源程序时才会发现可能的错误并报错.例如: #define PI 3.141 ...

  9. css实现视差滚动效果

    今天逛京东金融的时候发现他家网站首页的滚动效果看着很有意思,于是就做了一个,demo链接http://1.liwenyang.applinzi.com/index.html 大多数的视差滚动效果都是使 ...

  10. JXLS 2.4.0系列教程(四)——多sheet是怎么做到的

    注:本文代码在第一篇文章基础上修改而成,请务必先阅读第一篇文章. http://www.cnblogs.com/foxlee1024/p/7616987.html 本文也不会过多的讲解模板中遍历表达式 ...