3.3.3 零值机制
使用关键字var声明变量时,还会涉及“零值”这个概念,这也是Go语言的设计特色之一。零值机制指的是,如果提前为刚分配的内存指定了值,那么系统会把这块内存初始化成这个值,否则初始化为零值状态。零值机制的目的是减少Bug,它在确保Go代码的可靠性方面发挥着重要的作用。如果没有零值机制,且为变量分配了内存但并没有初始化,那么程序就会按照内存中原有的值继续运行。这可能一开始不会暴露出什么问题,但其状态肯定是错的。另外,如果不使用关键字var声明变量,那么它的值可能就不是零值。
使用var str string声明的字符串叫作空字符串。在Go语言中,字符串是由两个8字节组成的数据结构。比如在64位的架构中,一个字符串要占两个8字节也就是16字节。在这两个8字节中,第一个是指针,第二个是字节的数量。对于空字符串,指针是0;对于不需要指向存储字符内容的支撑数组,字节数自然也为0。
在Go语言中,编译器会确保变量为二进制零值,不过,我们阅读的“0”值和二进制零值不同。因为计算机只识别二进制,所以可以看到汇编中全是整数,其他类型(如浮点数)都是通过整数模拟的。许多语言都有自己的检查规则,比如在使用变量时必须确认是否已初始化,如果未初始化,则其值就是不确定的,这可能会产生不确定的逻辑,编译器在编译时会给出警告或者报错。Go语言在此处是基于工程语言的特点设计的,也就是说,只要拿到变量,就一定是初始化过的。对于全局变量,在编译代码之前会显式提供初始化值。对于局部变量,编译器通过插入类似MOVQ BP, 0x8(SP)等的汇编指令执行零值初始化操作。Go语言的变量声明机制在一定程度上保证了程序的可靠性。此外,因为有零值机制,所以使用关键字var声明变量时,可以保证变量至少能够初始化成全零的状态。表3-7列举了各类型对应的零值。
表3-7 各类型对应的零值
数组和结构体类型的零值是其每个元素对应类型的零值。从表3-7可以看到,所有引用类型的零值都是nil。