英文:
The zero value of a slice is not nil
问题
我正在为您翻译以下内容:
我按照https://tour.golang.org/moretypes/10的示例进行操作。我修改了代码,期望得到相同的结果。但实际上没有。这是一个错误还是文档错误?教程中提到:
> 一个空的切片的长度和容量都为0。
我的变量y的长度和容量都为0。
package main
import "fmt"
func myPrint(z []int) {
fmt.Println(z, len(z), cap(z))
if z == nil {
fmt.Println("nil!")
}
}
func main() {
var z []int
y := []int{}
myPrint(z)
myPrint(y)
}
这是我的输出结果。
[] 0 0
nil!
[] 0 0
我期望第二个"nil",为什么没有出现?
英文:
I was following the example https://tour.golang.org/moretypes/10
I modified the code expecting to get the same result. I did not. Is this a bug, or a documentation error? The tour states
> A nil slice has a length and capacity of 0.
My y variable has a length and capacity of 0.
package main
import "fmt"
func myPrint(z []int) {
fmt.Println(z, len(z), cap(z))
if z == nil {
fmt.Println("nil!")
}
}
func main() {
var z []int
y := []int {}
myPrint(z)
myPrint(y)
}
Here is my output.
[] 0 0
nil!
[] 0 0
I was expecting a second "nil"~ Why didn't I get it?
答案1
得分: 34
nil
与空
切片
如果我们将切片表示为:
[指针] [长度] [容量]
那么:
nil切片: [nil][0][0]
空切片: [地址][0][0] // 它指向一个地址
来自《Go in action》书籍:
nil切片
当你想表示一个不存在的切片时,它们非常有用,比如在返回切片的函数中发生异常时。
// 创建一个整数的nil切片。 var slice []int
空切片
当你想表示一个空集合时,空切片非常有用,比如当数据库查询返回零结果时。
// 使用make创建一个空的整数切片。 slice := make([]int, 0)
// 使用切片字面量创建一个空的整数切片。 slice := []int{}
👉 无论你使用nil切片还是空切片,内置函数
append
、len
和cap
的工作方式都是相同的。
package main
import (
"fmt"
)
func main() {
var nil_slice []int
var empty_slice = []int{}
fmt.Println(nil_slice == nil, len(nil_slice), cap(nil_slice))
fmt.Println(empty_slice == nil, len(empty_slice), cap(empty_slice))
}
输出结果为:
true 0 0
false 0 0
英文:
nil
Vs empty
slice
If we think of a slice like this:
[pointer] [length] [capacity]
then:
nil slice: [nil][0][0]
empty slice: [addr][0][0] // it points to an address
> From: "Go in action" book:
> ### nil slice
They’re useful when you want to represent a slice that doesn’t exist, such as when an exception occurs in a function that returns a slice.
> // Create a nil slice of integers.
> var slice []int
> ### empty slice
Empty slices are useful when you want to represent an empty collection, such as when a database query returns zero results.
> // Use make to create an empty slice of integers.
> slice := make([]int, 0)
> // Use a slice literal to create an empty slice of integers.
> slice := []int{}
> 👉 Regardless of whether you’re using a nil slice or an empty slice, the built-in functions append
, len
, and cap
work the same.
package main
import (
"fmt"
)
func main() {
var nil_slice []int
var empty_slice = []int{}
fmt.Println(nil_slice == nil, len(nil_slice), cap(nil_slice))
fmt.Println(empty_slice == nil, len(empty_slice), cap(empty_slice))
}
prints:
true 0 0
false 0 0
答案2
得分: 20
你引用的文档指出,一个空的切片的长度和容量都为0,但并不是说每个长度和容量为0的切片都是空切片。规范只是说一个未初始化的切片的值是nil。
这是为了方便支持对未初始化(nil)的切片使用len
和cap
。否则,我们需要先检查非nil值,以避免发生panic。(这也适用于其他内置类型,如映射或通道。)
就fmt.Print
的输出而言,行为上的差异类似于打印一个未初始化(nil)指针与打印指向空结构体的指针之间的区别:
var s *struct{} // 未初始化的指针
fmt.Println(s) // <nil>
s = &struct{}{} // 指向空结构体的指针
fmt.Println(s) // &{}
英文:
The doc you referenced states that a nil slice has a length and capacity of 0, but not that every slice of length and capacity of zero is a nil slice. The specification only says that the value of an uninitialized slice is nil.
This is a convenience to support len
and cap
on slices which are uninitialised (nil). Otherwise we would need to check for non-nil first in order to avoid panic. (This also holds for other in-built types like maps or channels.)
In terms of the fmt.Print
output, the difference in behaviour is similar to printing an uninitialised (nil) pointer vs pointer to an empty structure:
var s *struct{} // uninitialised pointer
fmt.Println(s) // <nil>
s = &struct{}{} // pointer to an empty structure
fmt.Println(s) // &{}
答案3
得分: 9
在这种情况下:
var z []int
你声明了一个变量 z
,但没有对其进行初始化。
在这种情况下:
y := []int {}
你声明并初始化了它,将其设置为空切片。以更长的方式编写第二个表达式可以更清楚地区分这两个表达式:
var y []int = []int {}
英文:
In this case:
var z []int
You have declared a variable z
but you did not initialize it.
In this case:
y := []int {}
You declared it and initialized it, you set it to an empty slice. Writing the second expression the long way makes the difference between the two expressions more clear:
var y []int = []int {}
答案4
得分: 6
你的 y
变量并不是切片的零值。它是通过一个空切片字面量进行分配的。
// 这两个都分配了一个切片
y := []int{}
z := []int{1, 2, 3}
英文:
Your y
variable isn't the zero value for a slice. It's allocated via an empty slice literal.
// both of these allocate a slice
y := []int{}
z := []int{1, 2, 3}
答案5
得分: 0
一个空切片的长度和容量都为0,并且没有底层数组。
var s []string => 没有底层数组
var s = []string => 创建了一个底层数组,但其长度为0。
英文:
> A nil slice has a length and capacity of 0 and has no underlying array.
var s []string => no underlying array
var s = []string => create a underlying array but his length is 0.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论