Estou tentando criar um método genérico em Go que preencherá um struct
usando dados de a map[string]interface{}
. Por exemplo, a assinatura e o uso do método podem ser semelhantes a:
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
Eu sei que isso pode ser feito usando JSON como um intermediário; existe outra maneira mais eficiente de fazer isso?
encoding/json
pacote stdlib para fazer essa etapa intermediária .. Você pode fornecer um mapa de exemplo e uma estrutura de exemplo em que este método pode ser usado?unsafe
pacote .. mas não me atrevo a tentar. Fora isso .. A reflexão é necessária, pois você precisa ser capaz de consultar os metadados associados a um tipo para colocar os dados em suas propriedades. Seria bastante simples envolver isso em chamadasjson.Marshal
+json.Decode
.. mas isso é o dobro do reflexo.Respostas:
A maneira mais simples seria usar https://github.com/mitchellh/mapstructure
Se você quiser fazer isso sozinho, pode fazer algo assim:
http://play.golang.org/p/tN8mxT_V9h
fonte
func (s MyStr...) FillStruct ...
para cada uma. É possível definir FillStruct para uma estrutura de base e fazer com que todas as minhas outras estruturas 'herdem' esse comportamento? No paradigma acima não é possível, pois apenas a estrutura de base ... neste caso "MyStruct" realmente terá seus campos iteradosA biblioteca https://github.com/mitchellh/mapstructure da Hashicorp faz isso fora da caixa:
O segundo
result
parâmetro deve ser um endereço da estrutura.fonte
user_name
e o campo de estrutura forUserName
?encoding/json
pacoteapenas por exemplo:
fonte
Você pode fazer isso ... pode ficar um pouco feio e você se deparará com algumas tentativas e erros em termos de tipos de mapeamento ... mas aqui está a essência disso:
Amostra de trabalho: http://play.golang.org/p/PYHz63sbvL
fonte
reflect: call of reflect.Value.Set on zero Value
Eu adapto a resposta de Dave e adiciono um recurso recursivo. Ainda estou trabalhando em uma versão mais amigável. Por exemplo, uma string numérica no mapa deve ser capaz de ser convertida em int na estrutura.
fonte
Existem duas etapas:
Abaixo está um exemplo:
fonte