本文介绍了为什么我不能追加到golang中结构属性的切片?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我试图给golang slice添加一个值,如果代码在第一个方法中被调用,代码就会工作,但如果这个方法调用另一个方法,代码似乎就失败了。
示例(Test3就是我最初试图做的):
package main
导入(
fmt
)
//这是可行的
类型Test1结构{
all [] int
}
func(c Test1)run()[] int {
for i:= 0;我< 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;我< 2; i ++ {
gloabl_all = append(gloabl_all,i)
}
}
//这不是
类型Test3结构{
all [] int
}
func(c Test3)run()[] int {
c.combo()
return c.all
func(c Test3)combo(){
for i:= 0;我< 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(),\\\
)
test2:=& Test2 {}
fmt.Println(Test2 final:,test2.run(),\\\
)
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:[]
游乐场副本:
任何帮助将不胜感激!
中的所有内容都是按值传递的。
Test3.combo()
有值(非指针)接收者:
$ b
func(c Test3)run()[] int {
c.combo()
返回c.all
}
func(c Test3)combo(){
for i:= 0;我< 2; i ++ {
c.all = append(c.all,i)
fmt.Println(Test3 step,i + 1,c.all)
}
}
这意味着当 Test3.combo()
是从> Test3.run()
,比如 c.combo()
,副本由 c
(它的类型是 Test3
)。 组合()
方法在副本上运行。它正确地附加了2个数字到 Test3.all
,但是当这个方法返回时,这个副本被放弃。
当 Test3.run()
返回 c.all
时,它返回一个空( nil
)切片,因为添加了 Test3.combo()
的切片是副本的一个字段,并且已被丢弃。
解决方案:只需使用指针接收器:
func(c * Test3) combo(){
for i:= 0;我< 2; i ++ {
c.all = append(c.all,i)
fmt.Println(Test3 step,i + 1,c.all)
}
}
输出(在):
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()
返回,更改不会丢失。
I'm trying to append a value to a golang slice, the code works if it's called in the first method, but if this method calls another method, the code seems to fail.
Examples (Test3 is what I was originally trying to do):
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())
}
This outputs:
Test1 final: [0 1]
Test2 final: [0 1]
Test3 step 1 [0]
Test3 step 2 [0 1]
Test3 final: []
Playground copy: https://play.golang.org/p/upEXINUvNu
Any help would be greatly appreciated!
解决方案
Everything in Go is passed by value. And a copy is made of the passed value.
Test3.combo()
has value (non-pointer) receiver:
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)
}
}
This means when Test3.combo()
is called from Test3.run()
like c.combo()
, a copy is made of c
(which is of type Test3
). The combo()
method operates on a copy. It properly appends 2 numbers to Test3.all
, but when this method returns, the copy is discarded.
So when Test3.run()
returns c.all
, it returns an empty (nil
) slice, because the slice to which Test3.combo()
appended, was a field of a copy, and which has been discarded.
Solution: simply use a pointer receiver:
func (c *Test3) combo() {
for i := 0; i < 2; i++ {
c.all = append(c.all, i)
fmt.Println("Test3 step", i + 1, c.all)
}
}
Output (try it on the Go Playground):
Test1 final: [0 1]
Test2 final: [0 1]
Test3 step 1 [0]
Test3 step 2 [0 1]
Test3 final: [0 1]
Note the star *
in the receiver: func (c *Test3) combo()
. By adding it, you make the receiver a pointer, and so when combo()
is called, it only receives a pointer to a value of type Test3
, and it will modify the pointed value, the value that Test3.run()
has, so when combo()
returns, the changes are not lost.
这篇关于为什么我不能追加到golang中结构属性的切片?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!