最近遇到了一个变量作用域的问题,一个比较低级的问题,可能作为一个熟手不应该犯这样的低级错误,但是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. Spring框架入门之基于xml文件配置bean详解

    关于Spring中基于xml文件配置bean的详细总结(spring 4.1.0) 一.Spring中的依赖注入方式介绍 依赖注入有三种方式 属性注入 构造方法注入 工厂方法注入(很少使用,不推荐,本 ...

  2. IdentityServer(15)- 第三方快速入门和示例

    这些示例不由IdentityServer团队维护. IdentityServer团队提供链接到了社区示例,但不能对示例做任何保证. 如有问题,请直接与作者联系. 各种ASP.NET Core安全示例 ...

  3. weui中的日期选择控件关于时间段的设置!

    近日用到了日期控件,但是需要把时和分去掉,功能上是做一个预约的功能,所以只需要在年月日后面提供时间段的选择. BUG在于如果第一次点开弹框而没做任何操作,然后点了其他任意区域则弹框关闭,甚至你的8:0 ...

  4. RabbitMQ的基本使用到高级特性

    简介 继上一篇 CentOS上安装RabbitMQ讲述RabbitMQ具体安装后,这一篇讲述RabbitMQ在C#的使用,这里将从基本用法到高级特性的使用讲述. 前序条件 这里需要增加一个用户,并且设 ...

  5. Codeforces 839C Journey【DFS】

    C. Journey time limit per test:2 seconds memory limit per test:256 megabytes input:standard input ou ...

  6. Codeforces Round #336 (Div. 2)-608A.水题 608B.前缀和

    A题和B题...   A. Saitama Destroys Hotel time limit per test 1 second memory limit per test 256 megabyte ...

  7. ASP.NET没有魔法——ASP.NET MVC & 分层 代码篇

    上一篇文章对如何规范使用ASP.NET进行了介绍,本章内容将根据上一篇得出的结论来修改博客应用的代码. 代码分层 综合考虑将博客应用代码分为以下几个层次: ○ 模型:代表应用程序中的数据模型,与数据库 ...

  8. Android初学:Gradle 'HelloWorld' project refresh failed

    Gradle 'HelloWorld' project refresh failed Error:Failed to open zip file.Gradle's dependency cache m ...

  9. C# delegate event func action 匿名方法 lambda表达式

    delegate event action func 匿名方法 lambda表达式 delegate类似c++的函数指针,但是是类型安全的,可以指向多个函数, public delegate void ...

  10. JavaScript八张思维导图

    JS基本概念 JS操作符 JS基本语句 JS数组用法 Date用法 JS字符串用法 JS编程风格 JS编程实践 不知不觉做前端已经五年多了,无论是从最初的jQuery还是现在火热的Angular,Vu ...