我正在尝试将一个值 append 到 golang slice ,如果在第一个方法中调用该代码,则代码有效,但如果此方法调用另一个方法,代码似乎会失败。
示例(Test3 是我最初尝试做的):
package main
import (
"fmt"
)
// This works
type Test1 struct {
all []int
}
func (c Test1) run() []int {
for i := 0; i < 2; i++ {
c.all = append(c.all, i)
}
return c.all
}
// This works
var gloabl_all []int
type Test2 struct {}
func (c Test2) run() []int {
c.combo()
return gloabl_all
}
func (c Test2) combo() {
for i := 0; i < 2; i++ {
gloabl_all = append(gloabl_all, i)
}
}
// This doesn't
type Test3 struct {
all []int
}
func (c Test3) run() []int {
c.combo()
return c.all
}
func (c Test3) combo() {
for i := 0; i < 2; i++ {
c.all = append(c.all, i)
fmt.Println("Test3 step", i + 1, c.all)
}
}
func main() {
test1 := &Test1{}
fmt.Println("Test1 final:", test1.run(), "\n")
test2 := &Test2{}
fmt.Println("Test2 final:", test2.run(), "\n")
test3 := &Test3{}
fmt.Println("Test3 final:", test3.run())
}
这个输出:
Test1 final: [0 1]
Test2 final: [0 1]
Test3 step 1 [0]
Test3 step 2 [0 1]
Test3 final: []
Playground 文案:https://play.golang.org/p/upEXINUvNu
如有任何帮助,我们将不胜感激!
最佳答案
Go 中的一切都是按值传递的。并且复制了传递的值。
Test3.combo()
有值(非指针)接收者:
func (c Test3) run() []int {
c.combo()
return c.all
}
func (c Test3) combo() {
for i := 0; i < 2; i++ {
c.all = append(c.all, i)
fmt.Println("Test3 step", i + 1, c.all)
}
}
这意味着当 Test3.combo()
像 c.combo()
一样从 Test3.run()
调用时,副本是由 c
(类型为 Test3
)组成。 combo()
方法对副本进行操作。它正确地将 2 个数字 append 到 Test3.all
,但是当此方法返回时,副本将被丢弃。
所以当 Test3.run()
返回 c.all
时,它返回一个空的 (nil
) slice ,因为 slice 到Test3.combo()
appended,是副本的字段,已被丢弃。
解决方案:简单地使用指针接收器:
func (c *Test3) combo() {
for i := 0; i < 2; i++ {
c.all = append(c.all, i)
fmt.Println("Test3 step", i + 1, c.all)
}
}
输出(在 Go Playground 上尝试):
Test1 final: [0 1]
Test2 final: [0 1]
Test3 step 1 [0]
Test3 step 2 [0 1]
Test3 final: [0 1]
注意接收器中的星号*
:func (c *Test3) combo()
。通过添加它,您使接收者成为一个指针,因此当 combo()
被调用时,它只接收一个指向 Test3
类型值的指针,并且它会修改指向的值,Test3.run()
具有的值,因此当 combo()
返回时,更改不会丢失。
关于go - 为什么我不能 append 到作为 golang 结构属性的 slice ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42274235/