Go 内置类型的零值

  1. 当一个变量被var声明之后,如果没有为其明确指明初始值,Go语言会自动初始化其值为此类型对应的零值。
类型 零值
integer 整数类型,包括的byterune 0
uintptr 整数类型 0
float 浮点数类型 0.0
bool 布尔值类型 false
string 字符串类型 空字符串""
complex 复数类型 0+0i
*T 指针类型 nil
interface、error、function、map、slice、channel nil

uintptr的默认值

  1. uintptr是整数类型不是指针,该类型只是用于指针地址做偏移运算。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package main

func main() {
    var s uintptr   // 0
    if s == 0 {
        print(123)
    }
    
    // Output:
    // 123
}

nil零值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package main

import (
    //"fmt"
)

func main() {
    // 此处编译不通过,nil赋值给x,编译器判断不出具体类型
    var x = nil	// use of untyped nil

    _ = x
}
  1. 在一个nil的切片中添加元素是没有问题的。
    • 因为nil的切片并没用分配内存,但是添加元素必须使用append函数,该函数会初始化nil的切片。(原因是会导致扩容从新分配内存)
  2. 但是对一个字典做同样的事将发生异常。
    • nilmap并没有分配内存,map添加元素是直接map[x] = x形式,所以会报错误。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main

import (
    "fmt"
)

func main() {
    // type sliceStruct struct {pointer, len, cap}
    // data=nil len=0 cap=0
    var a []string  // nil
    // 注意 与 a := []string{} 的区别,这种是已经初始化过的也就是系统默认调用过make方法其零值不为nil
    // 更多 var a []string 和 a := []string{} 形式将在切片一节中讨论
    // append 会初始化a
    a1 := append(a, "s")
    fmt.Println(a, a1)  // [] [s]

    //var m map[string]int
    //m["one"] = 1  // panic: assignment to entry in nil map

    // data len
    // make会初始化
    var m1 map[string]int = make(map[string]int, 2)
    m1["one"] = 1
    fmt.Println(m1)	// map[one:1]

    var ss *string = new(string)
    *ss = "abc"
    fmt.Println(ss, *ss)    // 0xc000088260 abc
    
    // panic: runtime error: invalid memory address or nil pointer dereference
    //var s *int    // 此时s的默认值为nil,*s并没有分配内存
    //*s = 10       // 报错 s 并没有分配内存空间
}
  1. 注意nil用于的类型:
    • nil是一个预先声明的标识符,表示a的零值 pointer, channel, func, interface, map, or slice type。
    • 类型必须是 pointer, channel, func, interface, map, or slice type.
1
2
var s string = "hello,world"
c := s[0] // c的类型为 byte 也就是 uint8