切片是对底层数组的引用。这是有道理的,似乎适用于内置/原始类型,但为什么不在结构上工作?我假设即使我更新结构字段,引用/地址仍然是相同的。
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)。
答案 0 :(得分:2)
调用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)
答案 1 :(得分:0)
来自GO FAQ:
与C系列中的所有语言一样,Go中的所有内容都通过 值。也就是说,一个函数总是得到一个东西的副本 传递,好像有一个赋值的赋值语句 到参数。例如,将int值传递给函数 制作int的副本,并传递指针值制作副本 指针,但不指向它指向的数据。 (参见下一节 讨论它如何影响方法接收器。)
Map和slice值的行为类似于指针:它们是描述符 包含指向底层地图或切片数据的指针。复制地图或 切片值不会复制它指向的数据。
因此,当您传递my
时,您传递的是结构的副本,并且调用代码不会看到对该副本所做的任何更改。
要让函数更改teh结构中的数据,必须将指针传递给结构。
答案 2 :(得分:0)
您的第三次测试与前两次测试不同。看看这个(Playground)。在这种情况下,您不需要使用指针,因为您没有修改切片本身。您正在修改基础数组的元素。如果要修改切片,例如,附加一个新元素,则需要使用指针通过引用传递切片。请注意,我更改了打印件以显示类型和值。