1. 切片的数据结构
// 参见reflect包
// slice的数据结构
type SliceHeader struct {
Data uintptr // 底层数组指针
Len int // 长度
Cap int // 容量
}
2. 零切片
func main() {
s1 := make([]int, 5)
s2 := make([]*int, 6)
fmt.Printf("s1:%+v s2:%+v \n", s1, s2)
// Pointer类型用于表示任意类型的指针
p1 := unsafe.Pointer(&s1)
p2 := unsafe.Pointer(&s2)
// 类型转换为切片底层数据结构
h1 := *(*reflect.SliceHeader)(p1)
h2 := *(*reflect.SliceHeader)(p2)
fmt.Printf("s1 %+v s2 %+v", h1, h2)
}
...
// 打印结果如下
s1:[0 0 0 0 0] s2:[<nil> <nil> <nil> <nil> <nil> <nil>]
s1 {Data:824633771040 Len:5 Cap:5} s2 {Data:824634229888 Len:6 Cap:6}
从打印结果可以看到,由make创建的,指针、长度、容量都不为0且内部数组元素都是0或nil的是零切片
3. nil切片
func main() {
var s1 []int
var s2 = *new([]int)
fmt.Printf("s1:%+v s2:%+v \n", s1, s2)
// Pointer类型用于表示任意类型的指针
p1 := unsafe.Pointer(&s1)
p2 := unsafe.Pointer(&s2)
// 类型转换为切片底层数据结构
h1 := *(*reflect.SliceHeader)(p1)
h2 := *(*reflect.SliceHeader)(p2)
fmt.Printf("s1 %+v s2 %+v", h1, h2)
}
...
// 打印结果如下
s1:[] s2:[]
s1 {Data:0 Len:0 Cap:0} s2 {Data:0 Len:0 Cap:0}
从打印结果可以看到,指针、长度、容量都为0的是nil切片
4. 空切片
func main() {
var s1 = []int{}
s2 := make([]int, 0)
fmt.Printf("s1:%+v s2:%+v \n", s1, s2)
// Pointer类型用于表示任意类型的指针
p1 := unsafe.Pointer(&s1)
p2 := unsafe.Pointer(&s2)
// 类型转换为切片底层数据结构
h1 := *(*reflect.SliceHeader)(p1)
h2 := *(*reflect.SliceHeader)(p2)
fmt.Printf("s1 %+v s2 %+v", h1, h2)
}
...
// 打印结果如下
s1:[] s2:[]
s1 {Data:5862168 Len:0 Cap:0} s2 {Data:5862168 Len:0 Cap:0}
从打印结果可以看到,指针不为0,长度、容量都为0的是空切片
5. 总结
- 零切片:由make创建,指针、长度、容量都不为0
- nil切片:指针、长度、容量都为0
- 空切片:指针不为0,长度、容量都为0