the sirve reservadas que programming primeros pasos para palabras lenguaje instalar google golang español codigo go

sirve - Método de golang con receptor de puntero.



primeros pasos en go (2)

Tengo este código de ejemplo

package main import ( "fmt" ) type IFace interface { SetSomeField(newValue string) GetSomeField() string } type Implementation struct { someField string } func (i Implementation) GetSomeField() string { return i.someField } func (i Implementation) SetSomeField(newValue string) { i.someField = newValue } func Create() IFace { obj := Implementation{someField: "Hello"} return obj // <= Offending line } func main() { a := Create() a.SetSomeField("World") fmt.Println(a.GetSomeField()) }

SetSomeField no funciona como se esperaba porque su receptor no es de tipo puntero.

Si cambio el método a un receptor de puntero, lo que esperaría que funcione, se ve así:

func (i *Implementation) SetSomeField(newValue string) { ...

Compilar esto lleva al siguiente error:

prog.go:26: cannot use obj (type Implementation) as type IFace in return argument: Implementation does not implement IFace (GetSomeField method has pointer receiver)

¿Cómo puedo hacer que la struct implemente la interfaz y el método SetSomeField cambie el valor de la instancia real sin crear una copia?

Aquí hay un fragmento hackeable: https://play.golang.org/p/ghW0mk0IuU

Ya he visto esta pregunta en go (golang), ¿cómo se puede convertir un puntero de interfaz en un puntero de estructura? , pero no puedo ver como se relaciona con este ejemplo.


La respuesta simple es que no podrá hacer que la estructura implemente su interfaz mientras que SetSomeField funcione de la manera que desee.

Sin embargo, un puntero a la estructura implementará la interfaz, por lo que cambiar su método Create para que return &obj debería hacer que las cosas funcionen.

El problema subyacente es que su método SetSomeField modificado SetSomeField no está en el conjunto de métodos de Implementation . Si bien la *Implementation del tipo *Implementation heredará los métodos del receptor sin puntero, lo contrario no es cierto.

El motivo de esto está relacionado con la forma en que se especifican las variables de la interfaz: la única forma de acceder al valor dinámico almacenado en una variable de la interfaz es copiarlo. Como ejemplo, imagina lo siguiente:

var impl Implementation var iface IFace = &impl

En este caso, una llamada a iface.SetSomeField funciona porque puede copiar el puntero para usar como el receptor en la llamada de método. Si almacenamos directamente una estructura en la variable de interfaz, deberíamos crear un puntero a esa estructura para completar la llamada al método. Una vez que se hace dicho puntero, es posible acceder (y potencialmente modificar) el valor dinámico de la variable de la interfaz sin copiarlo.


Su puntero a la estructura debe implementar la interfaz. De esa forma podrás modificar sus campos.

Mira cómo modifiqué tu código para que funcione como esperas:

package main import ( "fmt" ) type IFace interface { SetSomeField(newValue string) GetSomeField() string } type Implementation struct { someField string } func (i *Implementation) GetSomeField() string { return i.someField } func (i *Implementation) SetSomeField(newValue string) { i.someField = newValue } func Create() *Implementation { return &Implementation{someField: "Hello"} } func main() { var a IFace a = Create() a.SetSomeField("World") fmt.Println(a.GetSomeField()) }