问题的答案可能是"围棋就是这样的"但我想了解以下行为背后的原因,即对值类型的切片进行索引:
package main
import (
"fmt"
)
type S struct {
Data string
}
func main() {
s := []S{
{"first"},
{"second"},
{"third"},
}
// # 1
// This does not modify "s"
first := s[0]
first.Data = "something else"
fmt.Println(s)
// # 2
// ...but this does?
s[0].Data = "woah"
fmt.Println(s)
// # 3
// ...and this makes sense but feels inconsistent with the previous block
second := &s[1]
second.Data = "this makes sense"
fmt.Println(s)
}
我的问题是,既然var element S = s[0]
编译了,但var element *S = s[0]
不编译,为什么#2
更新切片?
(在操场上运行(
first := s[0]
创建s[0]
的副本并分配给first
,其类型为S
。
s[0].Data = "woah"
是直接分配,非常简单。
second := &s[1]
将指针分配给s[1]
到second
,其类型为*S
。所以second.Data
修改s[1].Data
是因为它是一个指针。请注意,Go对成员访问和指针访问都使用点(在C中,这将是->
运算符(。
写和理解这一点的等效方法是:
var first S
first = s[0]
var second *S
second = &s[1]