【问题标题】:Why are some slices nil?为什么有些切片为零?
【发布时间】:2023-02-25 04:32:24
【问题描述】:

我把这段代码放在一起来证明我的困惑: https://go.dev/play/p/HVp7p0w74Un

这两个切片 x 和 y 在数据(无)、长度和容量方面是相同的。但是其中一个是零,另一个不是。我理解这是事实,但我不明白为什么会这样。 基本上我正在尝试学习围棋,但我不知道如何思考它才能记住它。 那么,为什么 x 的计算结果为 nil 而 y 的计算结果却没有?

【问题讨论】:

标签: go


【解决方案1】:

如果它指向的底层数组为 nil,则 slice 为 nil。如果一个切片被初始化,即使它的容量为零,它也不是零。这有助于区分未初始化的切片和长度为 0 的切片。

在您的程序中,您可以将切片 y 分配给 nil:

y := make([]int, 0)
fmt.Println(y, len(y), cap(y)) // [] 0 0
fmt.Println(y == nil) // false
y = nil
fmt.Println(y == nil) // true
fmt.Println(y, len(y), cap(y)) // [] 0 0

【讨论】:

    【解决方案2】:

    The Go Programming Language Specification

    零值

    当通过声明或调用 new 为变量分配存储空间时,或者通过复合文字或调用 make 创建新值时,并且未提供显式初始化,则给出变量或值一个默认值。此类变量或值的每个元素都设置为其类型的零值:布尔值为 false,数字类型为 0,字符串为 "",指针、函数、接口、切片、通道和映射为 nil。

    切片的零值为 nil

    切片的实现

    type slice struct {
        array unsafe.Pointer
        len   int
        cap   int
    }
    

    零值是每个 struct 字段的零值,即每个 struct 字段的二进制零。

    【讨论】:

    • 那么这是否意味着 var x int 创建了一个名为 x 且值为 0 但没有分配内存的 int?
    • @Ramy:var x int 根据体系结构为int、64 位或32 位分配内存。
    • @Ramy:切片的零值,例如var []int,为切片实现类型分配内存。指向底层数组的指针的值为 nil(零)。
    【解决方案3】:

    制作Go 中的函数,将按照 capacity 参数中指定的方式分配内存。因此,它有一个非零引用。如果没有make,它只会声明切片而不会分配内存空间。因此,它指的是零。

    【讨论】:

      【解决方案4】:

      当您声明这样的切片时 var x []int 您正在创建一个零切片. 您实际上告诉编译器的是:“创建 []int 类型的切片”并且由于未分配任何值,因此 x 被分配了零 切片的值,为 nil.

      如果您不希望它为零,则需要用非零文字var x []int{}

      这里{}是一个空的数组文字和空并不意味着没有所以这个切片不是零切片。

      这在某种程度上等同于声明y := make([]int, 0)

      您还可以用数组文字中的一些值初始化一个切片:var x []int{1, 2, 3}

      【讨论】:

        猜你喜欢
        • 2021-11-04
        • 2015-08-28
        • 2013-05-13
        • 2021-08-22
        • 1970-01-01
        • 2016-03-22
        • 2018-10-02
        相关资源
        最近更新 更多