使用值接收器附加到具有足够容量的片

问题描述 投票:0回答:1

谁能帮我理解这里发生的事情?

package main

import (
    "fmt"
)

func appendString(slice []string, newString string) {
    slice = append(slice, newString)
}

func main() {
    slice := make([]string, 0, 1)
    appendString(slice, "a")
    fmt.Println(slice)
}

我知道切片头和使用指针接收器的需要。但是在这里,由于底层数组有足够的容量,我希望无论如何都可以附加工作(只需将新值添加到底层数组,并将原始[复制]标头按预期工作)

我的假设有什么问题?

pointers go append slice
1个回答
4
投票

让我们添加一个最终的print语句来查看结果:

slice := make([]string, 0, 1)
fmt.Println(cap(slice))
appendString(slice, "a")
fmt.Println(slice)

输出将是(在Go Playground上尝试):

1
[]

哪个是对的。可以预期输出为:

1
[a]

之所以不是这样的原因是因为即使不分配新的后备数组,slicemain()变量中的切片头也不会改变,它仍将保持length = 0。只有存储在slice(参数)内的appendString()局部变量中的切片头才会被更改,但此变量独立于main的slice

如果您要重新配置main的slice,您将看到支持数组确实包含新字符串:

slice := make([]string, 0, 1)
fmt.Println(cap(slice))
appendString(slice, "a")
fmt.Println(slice)

slice = slice[:1]
fmt.Println(slice)

现在输出将是(在Go Playground上尝试):

1
[]
[a]

这就是内置append()必须返回新切片的原因:因为即使不需要新的后备阵列,如果附加的元素超过0,则必须更改(增加)切片头(包含长度)。

这就是appendString()也应该返回新切片的原因:

func appendString(slice []string, newString string) []string {
    slice = append(slice, newString)
    return slice
}

或者简短:

func appendString(slice []string, newString string) []string {
    return append(slice, newString)
}

您必须重新分配使用它的位置:

slice := make([]string, 0, 1)
fmt.Println(cap(slice))
slice = appendString(slice, "a")
fmt.Println(slice)

然后你立即得到预期的结果(在Go Playground上尝试):

1
[a]
© www.soinside.com 2019 - 2024. All rights reserved.