nil是特定类型的未初始化状态,仅用于指针、slice、map等;零值是所有变量的默认初始值,如0、””、false等,二者概念不同但易混淆。

在 go 语言中,nil 和 空值(zero value) 是两个容易混淆但本质不同的概念。理解它们的区别对编写健壮的 Go 程序非常重要。
什么是 nil?
nil 是 Go 中预定义的标识符,表示某些类型的“零值指针”或“未初始化状态”。它只能用于以下类型:
- 指针类型(包括 *Type 和 unsafe.Pointer)
- slice
- map
- channel
- 函数类型(func)
- 接口类型(interface)
例如:
var p *int // p == nil var s []int // s == nil var m map[string]int // m == nil var c chan int // c == nil var f func() // f == nil var i interface{} // i == nil
注意:nil 不是关键字,而是一个预定义的标识符,不能用于其他类型,比如 int、string、struct 等。
立即学习“go语言免费学习笔记(深入)”;
什么是空值(Zero Value)?
Go 中每个变量都有一个默认的初始值,称为零值(zero value)。这是变量声明但未显式赋值时的默认状态。
不同类型的零值如下:
- 数值类型:0
- 布尔类型:false
- 字符串类型:””(空字符串)
- 指针/slice/map/channel/func/interface:nil
- 结构体:其所有字段为零值
例如:
var a int // a == 0 var b string // b == "" var c bool // c == false var d [3]int // d == [0, 0, 0]
nil 和空值的关键区别
虽然某些类型的零值是 nil,但这不意味着 nil 就等于“空”或“无效”。
以 slice 为例:
var s1 []int // s1 == nil,长度和容量都是 0 s2 := make([]int, 0) // s2 != nil,长度 0,容量 0 s3 := []int{} // s3 != nil,长度 0,容量 0
虽然 s1、s2、s3 都是“空切片”,但只有 s1 是 nil。判断时要注意:
fmt.Println(s1 == nil) // true fmt.Println(s2 == nil) // false fmt.Println(s3 == nil) // false
但在 range 遍历或 json 序列化时,三者行为可能一致。不过,在接口赋值中,nil 的传递很重要:
var s []int var i interface{} = s fmt.Println(i == nil) // false!因为 i 的动态类型是 []int,值为 nil slice
实际使用建议
在判断或返回集合类数据时,推荐统一使用 nil 或空切片,避免混淆。
- 函数返回空 slice 时,若无后续添加操作,可返回 nil 或 []T{},但要保持一致性
- 判断 slice 是否为空,应使用 len(s) == 0 而非 s == nil
- 在 JSON 序列化中,nil slice 会输出为 null,而 []T{} 输出为 [],需根据需求选择
基本上就这些。nil 是特定类型的“未初始化”状态,而零值是所有类型的默认初始值。有些类型的零值恰好是 nil,但两者概念不同。理解这一点有助于避免空指针、接口比较失败等问题。
js json go golang 区别 json String NULL 标识符 字符串 结构体 int 指针 接口 值类型 指针类型 布尔类型 Struct Interface 字符串类型 pointer 空指针 切片 len nil map channel


