nil slices vs non-nil slices vs empty slices in Go language
我是一个新手去编程。我在Go编程书中读到,切片由三个部分组成:指向数组的指针、长度和容量。
我在nil切片(slice没有要指向的基础数组,len=0,cap=0)和非nil切片(其中len=0,cap=0和空切片)之间感到困惑。
有人能告诉我零片和空片是不是一样的吗?如果两者都不一样,请告诉我两者有什么区别?
如何测试切片是否为空?
另外,指针在长度和容量为零的非零片中的值是什么?
可观察行为
- 您可以将它们传递给内置的
len() 和cap() 函数 - 您可以对它们执行
for range (将是0次迭代) - 您可以对它们进行切片(不违反spec:slice表达式中概述的限制;因此结果也将是一个空切片)
- 由于它们的长度为0,因此无法更改其内容(附加值将创建新的切片值)
- 所有切片(切片头)都有不同的内存地址
nil 片有0 数据指针s2 和s3 片具有相同的数据指针,共享/指向相同的0大小内存值
小精灵
参见这个简单的例子(一个
1 2 3 4 5 6 7 8 9 10 11 | var s1 []int // nil slice s2 := []int{} // non-nil, empty slice s3 := make([]int, 0) // non-nil, empty slice fmt.Println("s1", len(s1), cap(s1), s1 == nil, s1[:], s1[:] == nil) fmt.Println("s2", len(s2), cap(s2), s2 == nil, s2[:], s2[:] == nil) fmt.Println("s3", len(s3), cap(s3), s3 == nil, s3[:], s3[:] == nil) for range s1 {} for range s2 {} for range s3 {} |
输出(在游乐场上尝试):
1 2 3 | s1 0 0 true [] true s2 0 0 false [] false s3 0 0 false [] false |
号
(请注意,切片
您只能通过将切片值与预先声明的标识符
要判断切片是否为空,只需将其长度与
1 2 | s := make([]int, 0, 100) fmt.Println("Empty:", len(s) == 0,", but capacity:", cap(s)) |
印刷品(在游乐场上试用):
1 | Empty: true , but capacity: 100 |
。引擎盖下面
切片值由
1 2 3 4 5 | type SliceHeader struct { Data uintptr Len int Cap int } |
如果是
如果非
请注意,go规范允许具有0大小的不同类型的值具有相同的内存地址。规格:系统注意事项:尺寸和对准保证:
A struct or array type has size zero if it contains no fields (or elements, respectively) that have a size greater than zero. Two distinct zero-size variables may have the same address in memory.
号
让我们检查一下。为此,我们调用
1 2 3 4 5 6 7 8 9 10 11 12 13 | var s1 []int s2 := []int{} s3 := make([]int, 0) fmt.Printf("s1 (addr: %p): %+8v ", &s1, *(*reflect.SliceHeader)(unsafe.Pointer(&s1))) fmt.Printf("s2 (addr: %p): %+8v ", &s2, *(*reflect.SliceHeader)(unsafe.Pointer(&s2))) fmt.Printf("s3 (addr: %p): %+8v ", &s3, *(*reflect.SliceHeader)(unsafe.Pointer(&s3))) |
。
输出(在游乐场上尝试):
1 2 3 | s1 (addr: 0x1040a130): {Data: 0 Len: 0 Cap: 0} s2 (addr: 0x1040a140): {Data: 1535812 Len: 0 Cap: 0} s3 (addr: 0x1040a150): {Data: 1535812 Len: 0 Cap: 0} |
。
我们看到了什么?
小精灵
从字面意义上讲,切片可以为零:
1 2 | var n []int n == nil // true |
这是唯一容易的情况。"空"切片的概念没有很好的定义:一个带有
How to test whether a slice is empty or not?
号
"slice
Can anyone please tell whether nil and empty slices are same things? If they both are different, then please tell what is the difference between those two?
号
从技术上讲,零片和非零片是不同的(一个等于零,另一个等于零!=nil),但这种区别通常并不重要,因为可以将cx1〔35〕转换为nil切片,nil切片上的len和cap返回0
1 2 3 4 | var n []int len(n) == cap(n) == 0 // true n = append(n, 123) len(n) == 1 // true |
。
有关详细信息,请参阅Go中的零值。一个零切片就像一个零通道或一个零映射:它是未初始化的。您可以用
Also, what value does the pointer holds in non-nil slices, whose length and capacity are zero?
号
这是一个实现细节,可能因编译器而异,甚至因版本而异。没有人需要知道这一点来编写正确的便携式GO程序。