golang:变量的初始化

淩亂°似流年 2022-09-07 05:56 309阅读 0赞

我们知道,golang在声明变量时,自动对变量对应的内存区域进行初始化操作。每个变量会初始化其类型的默认值,比如:

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

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

回顾C语言

  • 在C语言中,变量在声明时,并不会对变量内存区域进行清理操作。此时,变量值可能是完全不可预期的结果。开发者需要习惯在使用C语言进行声明时要初始化操作,稍有不慎,就会造成不可预知的后果。
  • 在网络上只有程序员才能看懂的“烫烫烫”和“屯屯屯”的梗,就来源于 C/C++ 中变量默认不初始化。
  • 微软的VC编译器会将未初始化的栈空间以16进制的0xCC填充,而未初始化的堆空间使用0xCD填充,而 0xCCCC 和 0xCDCD 在中文的 GB2312 编码中刚好对应“烫”和“屯”字。
  • 因此,如果一个字符串没有结束符\0,直接输出的内存数据转换为字符串就刚好对应“烫烫烫”和“屯屯屯”。

变量初始化的标准格式

  1. 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 类型。
  • 第 5 行,输出 damage 的值。

以上代码输出结果为:

  1. 3.4

短变量声明并初始化

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

  1. hp := 100

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

  1. no new variables on left side of :=

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

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

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

net.Dial 提供按指定协议和地址发起网络连接,这个函数有两个返回值,一个是连接对象(conn),一个是错误对象(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 重复定义。

发表评论

表情:
评论列表 (有 0 条评论,309人围观)

还没有评论,来说两句吧...

相关阅读

    相关 golang变量作用域

    一个变量(常量、类型或函数)在程序中都有一定的作用范围,称之为作用域。 了解变量的作用域对我们学习Go语言来说是比较重要的,因为Go语言会在编译时检查每个变量是否使用过,一旦

    相关 golang:匿名变量

    在编码过程中,可能会遇到没有名称的变量、类型或方法。虽然这不是必须的,但有时候这样做可以极大地增强代码的灵活性,这些变量被统称为匿名变量。 匿名变量的特点是一个下画线“”,“

    相关 Java变量初始化

    1. Java中有两种变量,局部变量和成员变量。局部变量必须要初始化,否则编译时会报错,即局部变量必须要初始化赋值才能使用。 2. 但是类中的成员变量可以不进行初始化,虚拟

    相关 golang 全局变量

    在golang中,全局变量的生命周期属于整个包,这个和C不同,因为C语言没有包的概念。 在golang的main包中,main包定义的全局变量无法被其他包引用。 如果想使用