我正在尝试在Go中创建一个通用方法,它将填充struct来自a 的使用数据map[string]interface{}.例如,方法签名和用法可能如下所示:
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
Run Code Online (Sandbox Code Playgroud)
我知道这可以使用JSON作为中介来完成; 还有另一种更有效的方法吗?
dav*_*ave 81
最简单的方法是使用https://github.com/mitchellh/mapstructure
import "github.com/mitchellh/mapstructure"
mapstructure.Decode(myData, &result)
Run Code Online (Sandbox Code Playgroud)
如果你想自己做,你可以做这样的事情:
http://play.golang.org/p/tN8mxT_V9h
func SetField(obj interface{}, name string, value interface{}) error {
structValue := reflect.ValueOf(obj).Elem()
structFieldValue := structValue.FieldByName(name)
if !structFieldValue.IsValid() {
return fmt.Errorf("No such field: %s in obj", name)
}
if !structFieldValue.CanSet() {
return fmt.Errorf("Cannot set %s field value", name)
}
structFieldType := structFieldValue.Type()
val := reflect.ValueOf(value)
if structFieldType != val.Type() {
return errors.New("Provided value type didn't match obj field type")
}
structFieldValue.Set(val)
return nil
}
type MyStruct struct {
Name string
Age int64
}
func (s *MyStruct) FillStruct(m map[string]interface{}) error {
for k, v := range m {
err := SetField(s, k, v)
if err != nil {
return err
}
}
return nil
}
func main() {
myData := make(map[string]interface{})
myData["Name"] = "Tony"
myData["Age"] = int64(23)
result := &MyStruct{}
err := result.FillStruct(myData)
if err != nil {
fmt.Println(err)
}
fmt.Println(result)
}
Run Code Online (Sandbox Code Playgroud)
yun*_*ace 63
Hashicorp的https://github.com/mitchellh/mapstructure库开箱即用:
import "github.com/mitchellh/mapstructure"
mapstructure.Decode(myData, &result)
Run Code Online (Sandbox Code Playgroud)
第二个result参数必须是结构的地址.
Sim*_*ead 12
你可以做到......它可能会有点丑陋,你将面临一些试验和错误的映射类型..但继承人的基本要点:
func FillStruct(data map[string]interface{}, result interface{}) {
t := reflect.ValueOf(result).Elem()
for k, v := range data {
val := t.FieldByName(k)
val.Set(reflect.ValueOf(v))
}
}
Run Code Online (Sandbox Code Playgroud)
工作样本:http://play.golang.org/p/PYHz63sbvL
小智 8
您可以通过 JSON 往返它:
package main
import (
"bytes"
"encoding/json"
)
func transcode(in, out interface{}) {
buf := new(bytes.Buffer)
json.NewEncoder(buf).Encode(in)
json.NewDecoder(buf).Decode(out)
}
Run Code Online (Sandbox Code Playgroud)
例子:
package main
import "fmt"
type myStruct struct {
Name string
Age int64
}
func main() {
myData := map[string]interface{}{
"Name": "Tony",
"Age": 23,
}
var result myStruct
transcode(myData, &result)
fmt.Printf("%+v\n", result) // {Name:Tony Age:23}
}
Run Code Online (Sandbox Code Playgroud)
encoding/json包仅举例来说:
package main
import (
"fmt"
"encoding/json"
)
func Test() {
dict := make(map[string]interface{})
dict["id"] = 201902181425
dict["name"] = "jackytse"
dict["scores"] = 123.456
dict["address"] = map[string]string{"home":"address1", "company":"address2"}
dict["labels"] = []string{"aries", "warmhearted", "frank"}
jsonbody, err := json.Marshal(dict)
if err != nil {
// do error check
fmt.Println(err)
return
}
type AddressDefine struct {
Home string
Company string
}
type Student struct {
Id int64
Name string
Scores float32
Address AddressDefine
Labels []string
}
people := Student{}
if err := json.Unmarshal(jsonbody, &people); err != nil {
// do error check
fmt.Println(err)
}
fmt.Printf("%#v\n", people)
}
func main() {
Test()
}
Run Code Online (Sandbox Code Playgroud)
小智 5
有两个步骤:
下面是一个例子:
dbByte, _ := json.Marshal(dbContent)
_ = json.Unmarshal(dbByte, &MyStruct)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
64915 次 |
| 最近记录: |