切片的零值不是零

Rob*_*obs 11 go slice

我按照示例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)
}
Run Code Online (Sandbox Code Playgroud)

这是我的输出.

[] 0 0
nil!
[] 0 0
Run Code Online (Sandbox Code Playgroud)

我期待第二次"零"〜为什么我没有得到它?

tom*_*asz 14

您引用的文档声明nil切片的长度和容量为0,但并不是每个切片的长度和容量为零都是零切片.规范仅表示未初始化切片的值为零.

这是一种方便支持len和cap未初始化的片(零).否则我们需要首先检查非零,以避免恐慌.(这也适用于其他内置类型,如地图或频道.)

就fmt.Print输出而言,行为的差异类似于打印未初始化(零)指针与指向空结构的指针:

var s *struct{} // uninitialised pointer
fmt.Println(s)  // <nil>

s = &struct{}{} // pointer to an empty structure
fmt.Println(s)  // &{}
Run Code Online (Sandbox Code Playgroud)


tgo*_*gos 10

nilVs empty切片

如果我们想到这样的切片:

[pointer] [length] [capacity]
Run Code Online (Sandbox Code Playgroud)

然后:

nil slice:   [nil][0][0]
empty slice: [addr][0][0] // it points to an address
Run Code Online (Sandbox Code Playgroud)

来自:"开始行动"一书:

零切片

当您想要表示不存在的切片时,它们很有用,例如在返回切片的函数中发生异常时.

// Create a nil slice of integers.
var slice []int
Run Code Online (Sandbox Code Playgroud)

空切片

当您想要表示空集合时,例如当数据库查询返回零结果时,空切片很有用.

// 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{}
Run Code Online (Sandbox Code Playgroud)

不管您使用的是零片或空片,内置的功能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))

}
Run Code Online (Sandbox Code Playgroud)

打印:

true 0 0
false 0 0
Run Code Online (Sandbox Code Playgroud)


Aka*_*all 7

在这种情况下:

var z []int 
Run Code Online (Sandbox Code Playgroud)

您已声明了一个变量,z但未对其进行初始化.

在这种情况下:

y := []int {}
Run Code Online (Sandbox Code Playgroud)

您声明并初始化它,将其设置为空切片.长篇大论写第二个表达式使两个表达式之间的区别更加清晰:

var y []int = []int {}
Run Code Online (Sandbox Code Playgroud)


Jim*_*imB 5

您的y变量不是切片的零值.它是通过空切片文字分配的.

// both of these allocate a slice
y := []int{}
z := []int{1, 2, 3}
Run Code Online (Sandbox Code Playgroud)

  • @RobertJacobs:不,这是完全正确的 (2认同)