简体   繁体   English

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

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

The slices are references to the underlying array. 切片是对基础数组的引用。 This makes sense and seems to work on builtin/primitive types but why is not working on structs? 这是有道理的,似乎可以在内置/原始类型上使用,但是为什么不能在结构上使用呢? I assume that even if I update a struct field the reference/address is still the same. 我假设即使我更新了一个结构域,引用/地址也仍然相同。

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
}

To clarify: I'm aware that I could use pointers for both cases. 需要说明的是:我知道我可以在两种情况下都使用指针。 I'm only intrigued why the struct is not updated (unlike the int). 我只是对为什么不更新结构感兴趣(与int不同)。

What you do when calling update3 is you pass a new array, containing copies of the value, and you immediately discard the array. 调用update3时,您要做的是传递一个包含值副本的新数组,并立即丢弃该数组。 This is different from what you do with the primitive, as you keep the array. 这与保留原始数组不同,这与您使用原始函数所做的不同。

There are two approaches here. 这里有两种方法。

1) use an array of pointers instead of an array of values: 1)使用指针数组而不是值数组:

You could define update3 like this: 您可以这样定义update3

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

and call it using 并使用

update3([]*My{&my})

2) write in the array (in the same way you deal with the primitive) 2)在数组中写(以与处理原语相同的方式)

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

From the GO FAQ: GO常见问题解答:

As in all languages in the C family, everything in Go is passed by value. 与C系列中的所有语言一样,Go中的所有内容都按值传递。 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. 例如,将int值传递给函数将构成int的副本,而将指针值传递将使指针具有副本,但不会复制其指向的数据。 (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. 复制地图或切片值不会复制其指向的数据。

Thus when you pass my you are passing a copy of your struct and the calling code won't see any changes made to that copy. 因此,当您传递my您正在传递struct的副本,而调用代码将看不到对该副本所做的任何更改。

To have the function change the data in teh struct you have to pass a pointer to the struct. 要使函数更改struct中的数据,您必须将指针传递给struct。

Your third test is not the same as the first two. 您的第三项测试与前两项不同。 Look at this (Playground) . 看这个(操场) In this case, you do not need to use pointers as you are not modifying the slice itself. 在这种情况下,您不需要使用指针,因为您没有修改分片本身。 You are modifying an element of the underlying array. 您正在修改基础数组的元素。 If you wanted to modify the slice, by for instance, appending a new element, you would need to use a pointer to pass the slice by reference. 如果要修改切片,例如通过添加一个新元素,则需要使用指针通过引用传递切片。 Notice that I changed the prints to display the type as well as the value. 请注意,我更改了打印以显示类型和值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM