make initialize golang for example array go struct append slice

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.