Estoy tratando de crear un método genérico en Go que llenará un struct
uso de datos de un map[string]interface{}
. Por ejemplo, la firma y el uso del método podrían verse así:
func FillStruct(data map[string]interface{}, result interface{}) {
...
}
type MyStruct struct {
Name string
Age int64
}
myData := make(map[string]interface{})
myData["Name"] = "Tony"
myData["Age"] = 23
result := &MyStruct{}
FillStruct(myData, result)
// result now has Name set to "Tony" and Age set to 23
Sé que esto se puede hacer usando JSON como intermediario; ¿Existe otra forma más eficiente de hacer esto?
encoding/json
paquete stdlib para hacer ese paso intermedio ... ¿Puede dar un mapa de ejemplo y una estructura de ejemplo en la que este método podría usarse?unsafe
paquete ... pero no me atrevo a intentarlo. Aparte de eso ... Se requiere reflexión, ya que debe poder consultar los metadatos asociados con un tipo para colocar datos en sus propiedades. Sería bastante sencillo envolver esto enjson.Marshal
+json.Decode
llamadas ... pero eso es el doble de reflejo.Respuestas:
La forma más sencilla sería utilizar https://github.com/mitchellh/mapstructure
Si quiere hacerlo usted mismo, puede hacer algo como esto:
http://play.golang.org/p/tN8mxT_V9h
fuente
func (s MyStr...) FillStruct ...
para todas. ¿Es posible definir FillStruct para una estructura base y luego hacer que todas mis otras estructuras 'hereden' ese comportamiento? En el paradigma anterior no es posible ya que solo la estructura base ... en este caso, "MyStruct" tendrá sus campos iteradosLa biblioteca https://github.com/mitchellh/mapstructure de Hashicorp hace esto de inmediato :
El segundo
result
parámetro tiene que ser una dirección de la estructura.fuente
user_name
y la estructura archivada esUserName
?encoding/json
packagesolo por ejemplo:
fuente
Puede hacerlo ... puede ponerse un poco feo y se enfrentará a un poco de prueba y error en términos de tipos de mapeo ... pero aquí está la esencia básica:
Muestra de trabajo: http://play.golang.org/p/PYHz63sbvL
fuente
reflect: call of reflect.Value.Set on zero Value
Adapto la respuesta de Dave y agrego una característica recursiva. Todavía estoy trabajando en una versión más fácil de usar. Por ejemplo, una cadena de números en el mapa debería poder convertirse a int en la estructura.
fuente
Hay dos pasos:
A continuación se muestra un ejemplo:
fuente