对 slice ( [ ]int ) 的参数如何工作感到困惑?

confused about how parameter of slice ( [ ]int ) work?

我读了这个 article 做了一些样本,但我没能猜到其中一些的输出...

第一个(playground):

package main
import "fmt"
func surprise(a []int) {
    for i := range(a) {
        a[i] = 5
    }
    fmt.Println(a)
}
// Quiz #1
func main() {
    a := []int{1, 2, 3, 4}
    surprise(a)
    fmt.Println(a)
}

输出

[5 5 5 5]
[5 5 5 5]

第二个 (playground):

package main
import "fmt"
func surprise(a []int) {
    a = append(a, 5)
    for i := range(a) {
        a[i] = 5
    }
    fmt.Println(a)
}
// Quiz #2
func main() {
    a := []int{1, 2, 3, 4}
    surprise(a)
    fmt.Println(a)
}

输出:

[5 5 5 5 5]
[1 2 3 4]

所以我认为这是因为在第二个示例中切片值被复制到本地函数。 但后来我对第四个样本感到惊讶(playground):

package main
import "fmt"
func surprise(a []int) {
    a = append(a, 5)
    for i := range(a) {
        a[i] = 5
    }
    fmt.Println(a)
}
// Quiz #4
func main() {
    a := []int{1, 2, 3, 4}
    a = append(a, 5)
    surprise(a)
    fmt.Println(a)
}

输出:

[5 5 5 5 5 5]
[5 5 5 5 5]

那是为什么?

切片是数组的视图。当您将新值附加到容量不足的切片时,将分配一个具有更大容量的新数组,并将旧数组的内容复制到新数组。

所以在第二种情况下,切片被追加到函数中,所以此时分配了一个新数组,函数将新数组的所有值设置为5。main中的切片保持不变。

在第三种情况下,切片被追加到 main 中,这会创建一个两倍于原始数组大小的新数组。当函数向该数组追加一个新值时,不需要调整它的大小,因此 main 和函数都在同一个底层数组上工作,不同之处在于函数中的切片比 main 中的切片大 1。不过,它们都共享相同的底层数组。