1. 切片的数据结构

  1. // 参见reflect包
  2. // slice的数据结构
  3. type SliceHeader struct {
  4. Data uintptr // 底层数组指针
  5. Len int // 长度
  6. Cap int // 容量
  7. }

2. 零切片

  1. func main() {
  2. s1 := make([]int, 5)
  3. s2 := make([]*int, 6)
  4. fmt.Printf("s1:%+v s2:%+v \n", s1, s2)
  5. // Pointer类型用于表示任意类型的指针
  6. p1 := unsafe.Pointer(&s1)
  7. p2 := unsafe.Pointer(&s2)
  8. // 类型转换为切片底层数据结构
  9. h1 := *(*reflect.SliceHeader)(p1)
  10. h2 := *(*reflect.SliceHeader)(p2)
  11. fmt.Printf("s1 %+v s2 %+v", h1, h2)
  12. }
  13. ...
  14. // 打印结果如下
  15. s1:[0 0 0 0 0] s2:[<nil> <nil> <nil> <nil> <nil> <nil>]
  16. s1 {Data:824633771040 Len:5 Cap:5} s2 {Data:824634229888 Len:6 Cap:6}

从打印结果可以看到,由make创建的,指针、长度、容量都不为0且内部数组元素都是0或nil的是零切片

3. nil切片

  1. func main() {
  2. var s1 []int
  3. var s2 = *new([]int)
  4. fmt.Printf("s1:%+v s2:%+v \n", s1, s2)
  5. // Pointer类型用于表示任意类型的指针
  6. p1 := unsafe.Pointer(&s1)
  7. p2 := unsafe.Pointer(&s2)
  8. // 类型转换为切片底层数据结构
  9. h1 := *(*reflect.SliceHeader)(p1)
  10. h2 := *(*reflect.SliceHeader)(p2)
  11. fmt.Printf("s1 %+v s2 %+v", h1, h2)
  12. }
  13. ...
  14. // 打印结果如下
  15. s1:[] s2:[]
  16. s1 {Data:0 Len:0 Cap:0} s2 {Data:0 Len:0 Cap:0}

从打印结果可以看到,指针、长度、容量都为0的是nil切片

4. 空切片

  1. func main() {
  2. var s1 = []int{}
  3. s2 := make([]int, 0)
  4. fmt.Printf("s1:%+v s2:%+v \n", s1, s2)
  5. // Pointer类型用于表示任意类型的指针
  6. p1 := unsafe.Pointer(&s1)
  7. p2 := unsafe.Pointer(&s2)
  8. // 类型转换为切片底层数据结构
  9. h1 := *(*reflect.SliceHeader)(p1)
  10. h2 := *(*reflect.SliceHeader)(p2)
  11. fmt.Printf("s1 %+v s2 %+v", h1, h2)
  12. }
  13. ...
  14. // 打印结果如下
  15. s1:[] s2:[]
  16. s1 {Data:5862168 Len:0 Cap:0} s2 {Data:5862168 Len:0 Cap:0}

从打印结果可以看到,指针不为0,长度、容量都为0的是空切片

5. 总结

  • 零切片:由make创建,指针、长度、容量都不为0
  • nil切片:指针、长度、容量都为0
  • 空切片:指针不为0,长度、容量都为0