在 golang 中有 nil slice 和 empty slice 有啥意义?

Posted

技术标签:

【中文标题】在 golang 中有 nil slice 和 empty slice 有啥意义?【英文标题】:What is the point of having nil slice and empty slice in golang?在 golang 中有 nil slice 和 empty slice 有什么意义? 【发布时间】:2018-08-12 17:40:09 【问题描述】:

区分零切片有什么意义,即。未初始化的切片和一个空切片,即。已初始化但为空切片?

我了解其中的区别,但我想知道这两种情况之间存在细微差别的动机是什么?出于所有意图和目的,nil 切片和空切片在使用时的行为相同。

似乎 Go 开发人员只有一种情况,例如只允许空切片,它会简化思维模型并消除细微错误的来源。

创建这两个用例有什么原因吗?

【问题讨论】:

这和***.com/q/30806931/6309类似吗? 您还提到了哪些关于 nil 切片的细微错误? 在某些情况下,“盒子里没有苹果”和“没有盒子”之间存在细微差别。 我已经写了一个答案here,其中有来自“Go in action”一书的一些解释,可能会有所启发...... 【参考方案1】:

nil 切片值不需要分配。如果您想在切片中构建某些内容,但通常没有要附加的数据,因此切片可能保持nil,因此完全不需要分配,这可能会有所不同。

一个空切片可能需要分配,即使它的容量为零。

同样一个空切片意味着它的长度为0,但它的容量可能不是;所以 “出于所有意图和目的,nil 切片和空切片在使用它们时的行为是不正确的。”。您可以分配长度为 0 且容量大的切片,优化进一步追加以避免分配(和复制):

s := make([]int, 0)
fmt.Println(s, len(s), cap(s))
s = append(s, 1)
fmt.Println(s, len(s), cap(s))

s = make([]int, 0, 10)
fmt.Println(s, len(s), cap(s))
s = append(s, 1)
fmt.Println(s, len(s), cap(s))

上面的输出(在Go Playground上试试):

[] 0 0
[1] 1 2
[] 0 10
[1] 1 10

我们看到了什么?在第一个示例中,我们创建了一个长度为 0 且容量为 0 的空切片。如果我们向它附加一个元素,它的长度将变为 1(显然),并且它的容量增加到 2。这是因为在后台 append() 分配了一个大小为 2 的新数组(考虑到未来的增长),复制了现有元素(在这种情况下没有),并分配新元素。

在第二种情况下,我们从一个空切片开始,但容量为 10。这意味着我们可以向其追加 10 个元素,而不会导致新的分配和复制现有元素。当切片很大并且需要多次执行时,这可能是一个很大的优势。

【讨论】:

以上是关于在 golang 中有 nil slice 和 empty slice 有啥意义?的主要内容,如果未能解决你的问题,请参考以下文章

Golang Slice切片

golang中Array与Slice

golang源码之slice

Golang basic_leamingM 2023 1

golang的nil

golang源代码reflect.DeepEqual(x,y)函数