Tôi điều chỉnh câu trả lời của dave và thêm một tính năng đệ quy. Tôi vẫn đang làm việc trên một phiên bản thân thiện hơn với người dùng. Ví dụ, một chuỗi số trong bản đồ có thể được chuyển đổi thành int trong cấu trúc.
package main
import (
"fmt"
"reflect"
)
func SetField(obj interface{}, name string, value interface{}) error {
structValue := reflect.ValueOf(obj).Elem()
fieldVal := structValue.FieldByName(name)
if !fieldVal.IsValid() {
return fmt.Errorf("No such field: %s in obj", name)
}
if !fieldVal.CanSet() {
return fmt.Errorf("Cannot set %s field value", name)
}
val := reflect.ValueOf(value)
if fieldVal.Type() != val.Type() {
if m,ok := value.(map[string]interface{}); ok {
// if field value is struct
if fieldVal.Kind() == reflect.Struct {
return FillStruct(m, fieldVal.Addr().Interface())
}
// if field value is a pointer to struct
if fieldVal.Kind()==reflect.Ptr && fieldVal.Type().Elem().Kind() == reflect.Struct {
if fieldVal.IsNil() {
fieldVal.Set(reflect.New(fieldVal.Type().Elem()))
}
// fmt.Printf("recursive: %v %v\n", m,fieldVal.Interface())
return FillStruct(m, fieldVal.Interface())
}
}
return fmt.Errorf("Provided value type didn't match obj field type")
}
fieldVal.Set(val)
return nil
}
func FillStruct(m map[string]interface{}, s interface{}) error {
for k, v := range m {
err := SetField(s, k, v)
if err != nil {
return err
}
}
return nil
}
type OtherStruct struct {
Name string
Age int64
}
type MyStruct struct {
Name string
Age int64
OtherStruct *OtherStruct
}
func main() {
myData := make(map[string]interface{})
myData["Name"] = "Tony"
myData["Age"] = int64(23)
OtherStruct := make(map[string]interface{})
myData["OtherStruct"] = OtherStruct
OtherStruct["Name"] = "roxma"
OtherStruct["Age"] = int64(23)
result := &MyStruct{}
err := FillStruct(myData,result)
fmt.Println(err)
fmt.Printf("%v %v\n",result,result.OtherStruct)
}
encoding/json
gói stdlib để thực hiện bước trung gian đó .. Bạn có thể đưa ra một bản đồ ví dụ và cấu trúc ví dụ mà phương pháp này có thể được sử dụng không?