如何解决Go语言中的nil切片vs非nil切片vs空切片
可观察的行为
nil
和空片(容量为0)不同,但它们的可观察行为相同。我的意思是:
- 你可以将它们传递到内置
len()
和cap()
功能 - 您可以
for range
在它们之上(将为0次迭代) - 您可以对其进行切片(不违反Spec:Slice表达式中概述的限制;因此结果也将为空切片)
- 由于它们的长度为0,因此无法更改其内容(附加值将创建新的切片值)
请参见以下简单示例(一个nil
切片和2个非nil
空切片):
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 {}
输出(在Go Playground上尝试):
s1 0 0 true [] true
s2 0 0 false [] false
s3 0 0 false [] false
(请注意,对切片进行nil
切片会导致nil
切片,对非nil
切片进行切片会导致非nil
切片。)
您只能通过将slice值与预先声明的标识符进行比较来区分差异nil
,它们在其他各个方面的表现相同。
判断一个切片是空的,简单地比较其长度0
:len(s) ==
0
。是nil
切片还是非nil
切片都没有关系,是否具有正容量也没有关系。如果没有元素,则为空。
s := make([]int, 0, 100)
fmt.Println("Empty:", len(s) == 0, ", but capacity:", cap(s))
打印(在Go Playground上尝试):
Empty: true , but capacity: 100
引擎盖下
切片值由在中定义的结构表示reflect.SliceHeader
:
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
如果是nil
切片,则此结构的零值即为其所有字段的零值,即:0
。
具有非nil
片与容量和长度等于0
,Len
和Cap
场肯定会0
,但Data
指针可能不是。这 会
不会是,这就是从区别它nil
切片。它将指向大小为零的基础数组。
请注意,Go规范允许大小为0的不同类型的值具有相同的内存地址。规格:系统注意事项:尺寸和对齐保证:
如果结构或数组类型不包含大小大于零的字段(或元素),则其大小为零。
让我们检查一下。为此,我们调用unsafe
包的帮助,并“获取”reflect.SliceHeader
切片值的结构“视图”:
var s1 []int
s2 := []int{}
s3 := make([]int, 0)
fmt.Printf("s1 (addr: %p): %+8v\n",
&s1, *(*reflect.SliceHeader)(unsafe.Pointer(&s1)))
fmt.Printf("s2 (addr: %p): %+8v\n",
&s2, *(*reflect.SliceHeader)(unsafe.Pointer(&s2)))
fmt.Printf("s3 (addr: %p): %+8v\n",
&s3, *(*reflect.SliceHeader)(unsafe.Pointer(&s3)))
输出(在Go Playground上尝试):
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}
我们看到了什么?
- 所有片(片头)具有不同的内存地址
- 所述
nil
切片具有0
数据指针 -
s2
和s3
slice具有相同的数据指针,共享/指向相同的0大小的内存值
解决方法
我是Go编程的新手。我已经阅读了Go编程书籍,其中的内容由三部分组成:指向数组的指针,长度和容量。
我对nil slices(切片没有指向len的下层数组,len = 0,cap = 0),非lens切片(其中只有len = 0,cap =
0)和空切片之间感到困惑。
谁能告诉我nil和空片是否相同?如果两者都不相同,那么请说出两者之间的区别是什么?
如何测试切片是否为空?
另外,指针在长度和容量为零的非nil切片中保持什么值?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。