正如上一节《Go语言变量声明》中提到的 Go语言在声明变量时,自动对变量对应的内存区域进行初始化操作。每个变量会初始化其类型的默认值,例如:

  • 整型和浮点型变量的默认值为 0。
  • 字符串变量的默认值为空字符串。
  • 布尔型变量默认为 bool。
  • 切片、函数、指针变量的默认为 nil。


当然,依然可以在变量声明时赋予变量一个初始值。

回顾C语言


在C语言中,变量在声明时,并不会对变量对应内存区域进行清理操作。此时,变量值可能是完全不可预期的结果。开发者需要习惯在使用C语言进行声明时要初始化操作,稍有不慎,就会造成不可预知的后果。

在网络上只有程序员才能看懂的“烫烫烫”和“屯屯屯”的梗,就来源于C/C++中变量默认不初始化。

微软的 VC 编译器会将未初始化的栈空间以 16 进制的 0xCC 填充,而未初始化的堆空间使用 0xCD 填充,而 0xCCCC 和 0xCDCD 在中文的 GB2312 编码中刚好对应“烫”和“屯”字。

因此,如果一个字符串没有结束符\0,直接输出的内存数据转换为字符串就刚好对应“烫烫烫”和“屯屯屯”。

变量初始化的标准格式

var 变量名 类型 = 表达式


例如,游戏中,玩家的血量初始值为100。可以这样写:

  1. var hp int = 100


这句代码中,hp 为变量名,类型为 int,hp 的初始值为 100。

上面代码中,100 和 int 同为 int 类型,int 可以认为是冗余信息,因此可以进一步简化初始化的写法。

编译器推导类型的格式


在标准格式的基础上,将 int 省略后,编译器会尝试根据等号右边的表达式推导 hp 变量的类型。

  1. var hp = 100


等号右边的部分在编译原理里被称做右值(rvalue)。

下面是编译器根据右值推导变量类型完成初始化的例子。

  1. var attack = 40
  2. var defence = 20
  3. var damageRate float32 = 0.17
  4. var damage = float32(attack-defence) * damageRate
  5. fmt.Println(damage)


代码说明如下:

  • 第 1 和 2 行,右值为整型,attack 和 defence 变量的类型为 int。
  • 第 3 行,表达式的右值中使用了 0.17。Go 语言和C语言一样,编译器会尽量提高精确度,以避免计算中的精度损失。

    默认情况下,如果不指定 damageRate 变量的类型,Go 语言编译器会将 damageRate 类型推导为 float64。由于这个例子中不需要 float64 的精度,所以强制指定类型为 float32。

  • 第 4 行,将 attack 和 defence 相减后的数值结果依然为整型,使用 float32() 将结果转换为 float32 类型,再与 float32 类型的 damageRate 相乘后,damage 类型也是 float32 类型。

    提示:damage 变量的右值是一个复杂的表达式,整个过程既有 attack 和 defence 的运算还有强制类型转换。强制类型转换会在后面的章节中介绍。

  • 第 5 行,输出 damage 的值。



以上代码输出结果为:

3.4

短变量声明并初始化


var 的变量声明还有一种更为精简的写法,例如:

  1. hp := 100


这是 Go 语言的推导声明写法,编译器会自动根据右值类型推断出左值的对应类型。

注意:由于使用了:=,而不是赋值的=,因此推导声明写法的左值变量必须是没有定义过的变量。若定义过,将会发生编译错误。

如果 hp 已经被声明过,但依然使用:=时编译器会报错,代码如下:

  1. // 声明 hp 变量
  2. var hp int
  3. // 再次声明并赋值
  4. hp := 10


编译报错如下:

no new variables on left side of :=


意思是,在“:=”的左边没有新变量出现,意思就是“:=”的左边变量已经被声明了。

短变量声明的形式在开发中的例子较多,比如:

  1. conn, err := net.Dial("tcp","127.0.0.1:8080")


net.Dial 提供按指定协议和地址发起网络连接,这个函数有两个返回值,一个是连接对象,一个是 err 对象。如果是标准格式将会变成:

  1. var conn net.Conn
  2. var err error
  3. conn, err = net.Dial("tcp", "127.0.0.1:8080")


因此,短变量声明并初始化的格式在开发中使用比较普遍。

注意:在多个短变量声明和赋值中,至少有一个新声明的变量出现在左值中,即便其他变量名可能是重复声明的,编译器也不会报错,代码如下:

  1. conn, err := net.Dial("tcp", "127.0.0.1:8080")
  2. conn2, err := net.Dial("tcp", "127.0.0.1:8080")


上面的代码片段,编译器不会报err重复定义。

Go语言变量的初始化的更多相关文章

  1. C语言变量的初始化

    关于C语言变量是否需要初始化的问题.以前西北工业大学的C语言老师说的是,需要初始化,如果不初始化就使用的话,变量的值是以前遗留在内存中的,是不确定的(这只是针对局部变量的).C语言全局变量如果没有初始 ...

  2. c语言学习笔记-变量、变量的命名、变量的赋值和变量的初始化

    在学习了简单的输入输出功能和了解了一些基本的运算符号之后我们可以试着做一个非常简单的计算器. 比如说想计算23+65 输入以下代码就可以了. printf("23+65=%d",2 ...

  3. C语言全局未初始化数据段分析

    前言: 在分析C语言全局未初始化变量时,发现在目标文件中全局未初始化变量并不是直接放在bss段中. 再后来发现在两个.c文件中定义同名的全局变量,链接时居然没有发生符号重定义错误.才知道C语言弱定义的 ...

  4. [C语言 - 2] C语言变量

    A.变量的作用域: 1.局部变量:在函数或者代码块内部定义的变量 作用域:从定义处到代码块结束 生命周期:从定义处分配控件,代码块结束后被回收 局部变量没有默认值,要自己初始化   2.全局变量:在函 ...

  5. c语言数组不同初始化方式的结果

    第一种初始化方式: #include <stdio.h> int main() { int numbers[5]={12,14}; for (int i=0; i<5; i++) { ...

  6. Go 语言变量

    变量来源于数学,是计算机语言中能储存计算结果或能表示值抽象概念.变量可以通过变量名访问. Go 语言变量名由字母.数字.下划线组成,其中首个字母不能为数字. 声明变量的一般形式是使用 var 关键字: ...

  7. C语言 变量的作用域和生命周期(转)

    转自 https://blog.csdn.net/u011616739/article/details/62052179 a.普通局部变量 属于某个{},在{}外部不能使用此变量,在{}内部是可以使用 ...

  8. go语言变量

    变量可以通过变量名访问 Go 语言变量名由字母.数字.下划线组成,其中首个字符不能为数字 声明变量的一般形式是使用 var 关键字: var identifier type 变量声明 1. 指定变量类 ...

  9. C语言变量声明内存分配

    转载: C语言变量声明内存分配   一个由c/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)— 程序运行时由编译器自动分配,存放函数的参数值,局部变量的值等.其操作方式类似于数据结 ...

随机推荐

  1. 前端微信小程序云开发基础讲解

    什么是云开发 云开发与传统模式的对比 云开发能力介绍云开发对小程序开发的变革 云开发是微信团队联合腾讯云提供的原生serverless云服务,致力于帮助更多的开发者快速实现小程序业务的开发,快速迭代. ...

  2. Cocos Creator打包发布

    若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理. 请点赞!因为你们的赞同/鼓励是我写作的最大动力! 欢迎关注达叔小生的简书! 这是一个有质量 ...

  3. shell脚本编程之变量的小用法

    变量赋值 ${parameter:-word}:如果parameter为空或未定义,则变量展开为"word":否则,展开为parameter的值: ${parameter:+wor ...

  4. GoCN每日新闻(2019-10-24)

    GoCN每日新闻(2019-10-24) GoCN每日新闻(2019-10-24) 1. 学习Golang之服务器框架编写 – CS网络通信 http://1t.click/aJag 2. 如何实现 ...

  5. Clouds Classification from Sentinel-2 Imagery with Deep Residual Learning and Semantic Image Segmentation

    哨兵2号云检测的语义分割,提出了CloudNet,不使用池化和上采样操作,从头到尾保持原图大小,中间每个块使用ASPP和残差连接,网络结构如下 比较了CNN, FCN, DeeplabV3+,效果都没 ...

  6. 刷题记录:[SUCTF 2019]CheckIn

    目录 刷题记录:[SUCTF 2019]CheckIn 一.涉及知识点 1.利用.user.ini上传\隐藏后门 2.绕过exif_imagetype()的奇技淫巧 二.解题方法 刷题记录:[SUCT ...

  7. 20189220 余超《Linux内核原理与分析》第四周作业

    构造一个简单的Linux系统MenuOS 第三章基础知识 计算机的三大法宝:存储计算机,函数调用堆栈,中断. 操作系统的两把宝剑:中断上下文,进程上下文. Linux内核源码的目录结构: arch目录 ...

  8. Service Fabric独立集群搭建

    开篇声明:巨坑,慎入.若实则无奈,建议直接上azure... 1.  开启服务器自动更新,安装最新的补丁. 2.  下载用于 Windows Server 的 Service Fabric 包(htt ...

  9. Python3基础 dict __len__ 统计键值对的数量

             Python : 3.7.3          OS : Ubuntu 18.04.2 LTS         IDE : pycharm-community-2019.1.3    ...

  10. Qt开发经验小技巧11-20

    获取类的属性 const QMetaObject *metaobject = object->metaObject(); int count = metaobject->propertyC ...