initialize - ¿Por qué no puedo agregar a una porción que es propiedad de una estructura en golang?
maps en golang (1)
Estoy intentando agregar un valor a una porción de golang, el código funciona si se llama en el primer método, pero si este método llama a otro método, el código parece fallar.
Ejemplos (Test3 es lo que originalmente estaba tratando de hacer):
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())
}
Esto produce:
Test1 final: [0 1]
Test2 final: [0 1]
Test3 step 1 [0]
Test3 step 2 [0 1]
Test3 final: []
Copia de patio de recreo: https://play.golang.org/p/upEXINUvNu
¡Cualquier ayuda sería muy apreciada!
Todo en Go pasa por valor. Y una copia está hecha del valor pasado.
Test3.combo()
tiene receptor de valor (no puntero):
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)
}
}
Esto significa que cuando se llama a Test3.run()
desde Test3.run()
como c.combo()
, se realiza una copia de c
(que es del tipo Test3
). El método combo()
opera en una copia. Test3.all
apropiadamente 2 números a Test3.all
, pero cuando este método retorna, la copia se descarta.
Por lo tanto, cuando Test3.run()
devuelve c.all
, devuelve un segmento vacío ( nil
), porque el segmento al que Test3.combo()
agregó, era un campo de una copia y se ha descartado.
Solución: simplemente use un receptor de puntero:
func (c *Test3) combo() {
for i := 0; i < 2; i++ {
c.all = append(c.all, i)
fmt.Println("Test3 step", i + 1, c.all)
}
}
Salida (pruébalo en el área de juegos Go ):
Test1 final: [0 1]
Test2 final: [0 1]
Test3 step 1 [0]
Test3 step 2 [0 1]
Test3 final: [0 1]
Tenga en cuenta la estrella *
en el receptor: func (c *Test3) combo()
. Al agregarlo, hace que el receptor sea un puntero, por lo que cuando se llama a combo()
, solo recibe un puntero a un valor de tipo Test3
, y modificará el valor en punta, el valor que tiene Test3.run()
, entonces cuando combo()
regresa, los cambios no se pierden.