¿Las asignaciones de vectores se copian por valor o por referencia en el idioma Go de Google?
Pregunta
En el siguiente código, creo un rompecabezas de clavija y luego hago un movimiento en él que agrega un movimiento a su vector de movimientosAlreadyDone. Luego creo otro rompecabezas de clavijas y luego hago un movimiento en él que agrega un movimiento a su vector de movimientosAlreadyDone. Cuando imprimo los valores en ese vector para el segundo, tiene el movimiento desde el primero junto con el movimiento desde el segundo. ¿Alguien puede decirme por qué parece estar asignando por referencia y no por valor? ¿Las asignaciones de vectores se copian por valor o por referencia en el idioma Go de Google?
package main
import "fmt"
import "container/vector"
type Move struct { x0, y0, x1, y1 int }
type PegPuzzle struct {
movesAlreadyDone * vector.Vector;
}
func (p *PegPuzzle) InitPegPuzzle(){
p.movesAlreadyDone = vector.New(0);
}
func NewChildPegPuzzle(parent *PegPuzzle) *PegPuzzle{
retVal := new(PegPuzzle);
retVal.movesAlreadyDone = parent.movesAlreadyDone;
return retVal
}
func (p *PegPuzzle) doMove(move Move){
p.movesAlreadyDone.Push(move);
}
func (p *PegPuzzle) printPuzzleInfo(){
fmt.Printf("-----------START----------------------\n");
fmt.Printf("moves already done: %v\n", p.movesAlreadyDone);
fmt.Printf("------------END-----------------------\n");
}
func main() {
p := new(PegPuzzle);
cp1 := new(PegPuzzle);
cp2 := new(PegPuzzle);
p.InitPegPuzzle();
cp1 = NewChildPegPuzzle(p);
cp1.doMove(Move{1,1,2,3});
cp1.printPuzzleInfo();
cp2 = NewChildPegPuzzle(p);
cp2.doMove(Move{3,2,5,1});
cp2.printPuzzleInfo();
}
Cualquier ayuda será muy apreciada. Gracias!
Solución
Incidental a la respuesta, pero vector.New
se ha eliminado de las versiones recientes de Go. Necesitas escribir
func (p *PegPuzzle) InitPegPuzzle(){
p.movesAlreadyDone = new (vector.Vector);
}
En su código original, las cosas que está copiando son punteros a vectores. Esto es lo mismo que los punteros en C. Puede llamarlo " por referencia " Si quieres, pero son punteros.
Para copiar un vector completo, use InsertVector
:
func (p *PegPuzzle) InitPegPuzzle(){
p.movesAlreadyDone = new (vector.Vector);
}
func NewChildPegPuzzle(parent *PegPuzzle) *PegPuzzle{
retVal := new (PegPuzzle);
retVal.InitPegPuzzle ();
retVal.movesAlreadyDone.InsertVector (0, parent.movesAlreadyDone);
return retVal
}
Esto da una copia única completa.
Otros consejos
En su código, movesAlreadyDone
es un * vector.Vector
; cuando asigna retVal.movesAlreadyDone = parent.movesAlreadyDone;
, está copiando una referencia. Cada vez que se realice una modificación vectorial en retVal.movesAlreadyDone
o parent.movesAlreadyDone
, se modificará el mismo vector subyacente.
Si desea copiar el contenido de un vector a otro, deberá recorrer el vector de origen y enviar sus elementos al vector de destino. Al igual que:
for n := range srcVect.Iter() {
dstVect.Push(n);
}