为什么我不能附加到 golang 中结构的 属性 的切片?
Why can't I append to a slice that's the property of a struct in golang?
我正在尝试将一个值附加到 golang 切片,如果在第一个方法中调用该代码,则代码有效,但如果此方法调用另一个方法,代码似乎会失败。
例子(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: []
游乐场副本:https://play.golang.org/p/upEXINUvNu
如有任何帮助,我们将不胜感激!
Go 中的一切都是按值传递的。并且复制了传递的值。
Test3.combo()
有值 (non-pointer) 接收方:
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.run()
像 c.combo()
一样调用 Test3.combo()
时,会复制 c
(类型为 Test3
)。 combo()
方法对副本进行操作。它正确地将 2 个数字附加到 Test3.all
,但是当此方法 returns 时,副本被丢弃。
所以当 Test3.run()
returns c.all
时,它 returns 一个空的 (nil
) 切片,因为 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()
returns时,修改没有丢失。
我正在尝试将一个值附加到 golang 切片,如果在第一个方法中调用该代码,则代码有效,但如果此方法调用另一个方法,代码似乎会失败。
例子(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: []
游乐场副本:https://play.golang.org/p/upEXINUvNu
如有任何帮助,我们将不胜感激!
Go 中的一切都是按值传递的。并且复制了传递的值。
Test3.combo()
有值 (non-pointer) 接收方:
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.run()
像 c.combo()
一样调用 Test3.combo()
时,会复制 c
(类型为 Test3
)。 combo()
方法对副本进行操作。它正确地将 2 个数字附加到 Test3.all
,但是当此方法 returns 时,副本被丢弃。
所以当 Test3.run()
returns c.all
时,它 returns 一个空的 (nil
) 切片,因为 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()
returns时,修改没有丢失。