使用 Go 范围语法时的意外行为



可能只是因为我是 Go 新手,但是在结构数组上使用范围语法的行为并不像我期望的那样。我假设数组项被复制到范围索引,但副本不是深层副本......所以下面有点奇怪。这种行为是否记录在某处

package main
import "fmt"
type Inner struct {
x, y int
}
type Attr struct {
a      int
inside []Inner
}
var item = []Attr{
{a: 1, inside: []Inner{{2, 3}, {3, 4}}},
{a: 2, inside: []Inner{{3, 4}, {1, 2}}},
}
func main() {
fmt.Println(item) 
for _,i := range item {
// A: The following has no impact on item[].a
i.a = 111
// B: But this does ... why?
i.inside[0].x = 111
}
fmt.Println(item) 
for j,_  := range item {
item[j].a = 333
item[j].inside[0].x = 333
}
fmt.Println(item)
}

在循环for _, i := range item中,每个i都是相应切片元素的副本。假设,你写:

i := item[0]
i.a = 111

这不会更改切片的原始元素,而只会更改其副本。但是在:

i.inside[0].x = 111

inside是一个切片,即只是一个引用底层数组的薄包装器,在分配时不会复制。因此,使用i.inside,您可以处理与items[0].inside相同的切片。

有关切片内部的更多信息。

最新更新