例如:
package main
import "fmt"
type Test struct {
elems []string
}
func main() {
initial := Test{
elems: make([]string, 0),
}
initial.elems = append(initial.elems, "apple")
fmt.Println(initial.elems) // #1 [apple]
s := make([]Test, 0)
s = append(s, initial)
initial.elems = append(initial.elems, "bannana")
fmt.Println(initial.elems) // #2 [apple bannana]
fmt.Println(s[0].elems) // #3 [apple]
second := s[0]
second.elems = append(second.elems, "carrot")
fmt.Println(second.elems) // #4 [apple bannana]
}
我正在寻求帮助以了解打印声明#3和#4。在#3中,我期望[apple bannana]
;在#4中,我期望[apple bannana carrot]
。
据我了解,作为切片的elems
字段是通过引用自动传递的,因此我在上述代码块中所做的每个追加都应修改基础数组。但是,显然不是这样。
所以,我的问题是:initial
插入切片后会怎样呢?另外,如何编写此代码以在打印语句#4上获得预期结果?
答案 0 :(得分:3)
在Golang中被提及:
映射和切片值的行为类似于指针:它们是 包含指向基础地图或切片数据的指针。复制地图或 切片值不会复制其指向的数据。
添加到切片s
的方式是通过将Test结构的副本添加到s
切片来创建新切片。因此,您没有设置指向原始Test
结构的指针。这样,如果数据在结构内部发生变化,它也将反映在切片中。这是您面临的问题。
initial.elems = append(initial.elems, "apple")
fmt.Println(initial.elems) // #1 [apple]
s := make([]Test, 0) // this should be pointer to the struct to have teh changes in future to original struct.
s = append(s, initial) // appending to the s slice
在制作切片Test
时创建指向s
结构的指针,只要您更改原始结构中的元素,它就会反映出更改。例如:
package main
import "fmt"
type Test struct {
elems []string
}
func main() {
initial := Test{
elems: make([]string, 0),
}
initial.elems = append(initial.elems, "apple")
fmt.Println(initial.elems) // #1 [apple]
s := make([]*Test, 0) // create a pointer to Test struct.
s = append(s, &initial)
initial.elems = append(initial.elems, "bannana")
fmt.Println(initial.elems) // #2 [apple bannana]
fmt.Printf("%+v\n",*s[0]) // #3 [apple banana]
second := s[0]
second.elems = append(second.elems, "carrot")
fmt.Println(second.elems) // #4 [apple bannana carrot]
}
输出:-
[apple]
[apple bannana]
{elems:[apple bannana]}
[apple bannana carrot]
Go Playground上的工作代码
答案 1 :(得分:1)
这是由事实引起的,initial
变量与s[0]
不同-它们是两个独立的Test
变量,追加到一个变量不会更改第二个变量。传递给initial
时,append()
被按值复制到另一个对象
证明:
fmt.Printf("second: %p, initial: %p\n", &second.elems[0], &initial.elems[0])
(其中second.elems[0] == "apple"
和initial.elems[0] == "apple"
)
输出
second: 0xc00000a120, initial: 0xc00000a0c0
这表明这是真的