为什么 slice []struct 的行为与 []builtin 不同?

Why a slice []struct doesn't behave same as []builtin?

切片是对底层数组的引用。这是有道理的,似乎适用于 builtin/primitive 类型,但为什么不适用于结构?我假设即使我更新了一个结构字段,reference/address 仍然是一样的。

package main

import "fmt"

type My struct {
    Name string
}

func main() {
    x := []int{1}
    update2(x)
    fmt.Println(x[0])
    update(x)
    fmt.Println(x[0])
    my := My{Name: ""}
    update3([]My{my})
    // Why my[0].Name is not "many" ?
    fmt.Println(my)
}

func update(x []int) {
    x[0] = 999
    return
}
func update2(x []int) {
    x[0] = 1000
    return
}
func update3(x []My) {
    x[0].Name = "many"
    return
}

澄清一下:我知道我可以对这两种情况使用指针。我只是好奇为什么结构没有更新(不像 int)。

调用 update3 时所做的是传递一个包含值副本的新数组,然后立即丢弃该数组。这与您对原语所做的不同,因为您保留数组。

这里有两种方法。

1) 使用指针数组而不是值数组:

您可以这样定义 update3

func update3(x []*My) {
    x[0].Name = "many"
    return
}

并使用

调用它
update3([]*My{&my})

2)写在数组中(和你处理原语一样)

arr := make([]My,1)
arr[0] = My{Name: ""}
update3(arr)

来自GO FAQ:

As in all languages in the C family, everything in Go is passed by value. That is, a function always gets a copy of the thing being passed, as if there were an assignment statement assigning the value to the parameter. For instance, passing an int value to a function makes a copy of the int, and passing a pointer value makes a copy of the pointer, but not the data it points to. (See the next section for a discussion of how this affects method receivers.)

Map and slice values behave like pointers: they are descriptors that contain pointers to the underlying map or slice data. Copying a map or slice value doesn't copy the data it points to.

因此,当您传递 my 时,您传递的是结构的副本,调用代码不会看到对该副本所做的任何更改。

要让函数更改结构中的数据,您必须传递一个指向该结构的指针。

您的第三次测试与前两次不同。看看这个(Playground)。在这种情况下,您不需要使用指针,因为您没有修改切片本身。您正在修改基础数组的元素。如果你想修改切片,例如,通过附加一个新元素,你需要使用一个指针来通过引用传递切片。请注意,我更改了打印以显示类型和值。