Go 语言中各类数据类型的零值详解

go 语言为未显式初始化的变量自动赋予“零值”(zero value),不同类型的零值各不相同:布尔型为 false,数值型为 0,字符串为空串,指针/函数/接口/切片/通道/映射均为 nil,且该规则递归适用于复合类型。

在 Go 中,零值是类型安全与内存确定性的基石。当你声明一个变量但未赋初值(如 var x int),Go 不会留空或使用随机内存值,而是严格依据类型赋予预定义的零值。这一机制消除了未初始化变量引发的不确定性,也使代码更可预测、更易调试。

以下是常见内置类型的零值对照表:

类型 零值 示例声明
bool false var b bool → b == false
int / int64 等 0 var n int → n == 0
float32 / float64 0.0 var f float64 → f == 0.0
string ""(空字符串) var s string → s == ""
*T(指针) nil var p *int → p == nil
func() nil var fn func() int → fn == nil
interface{} nil var i interface{} → i == nil
[]T(切片) nil var sl []byte → sl == nil(注意:非空切片但 len=0 时 ≠ nil)
map[K]V nil var m map[string]int → m == nil
chan T nil var c chan int → c == nil

⚠️ 重要说明

  • 复合类型递归应用零值:例如 type Person struct { Name string; Age int },则 var p Person 中 p.Name 为 "",p.Age 为 0;数组 var a [3]int 的每个元素均为 0。
  • new(T) 返回指向零值的指针(如 new(int) 返回 *int 指向 0);
  • make(T, ...) 仅用于 slice/map/channel,返回已初始化(非 nil)但内容为零值的实例(如 make([]int, 2) 返回长度为 2、元素全为 0 的切片,而非 nil)。

✅ 实际验证示例:

package main

import "fmt"

func main() {
    var b bool
    var i int
    var f float64
    var s string
    var p *int
    var m map[string]int
    var sl []int
    var ch chan int

    fmt.Printf("bool: %t\n", b)           // false
    fmt.Printf("int: %d\n", i)           // 0
    fmt.Printf("float64: %g\n", f)       // 0
    fmt.Printf("string: %q\n", s)        // ""
    fmt.Printf("pointer: %v\n", p)       // 
    fmt.Printf("map: %v\n", m)           // map[]
    fmt.Printf("slice: %v\n", sl)        // []
    fmt.Printf("channel: %v\n", ch)      // 
}

掌握零值规则对编写健壮 Go 代码至关重要——它影响 nil 检查逻辑(如 if m == nil)、结构体字段默认行为、以及 == 比较的安全性(注意:含 nil 指针或函数的结构体可安全比较,但含 map/slice/chan 的结构体不可直接比较)。始终牢记:Go 没有“未定义值”,只有明确的零值