阅读背景:

golang struct 转map 及 map[string]*Struct 初始化和遍历_weixin_30900589的博客

来源:互联网 
package main

import (
    "encoding/json"
    "errors"
    "fmt"
    "reflect"
    "strconv"
    "time"
)

type User struct {
    a string
    b string
}

type S struct {
    User
    Name    string
    Age     int
    Address string
}

//结构体转map方法1
func Struct2Map(obj interface{}) map[string]interface{} {
    t := reflect.TypeOf(obj)
    v := reflect.ValueOf(obj)

    var data = make(map[string]interface{})
    //func (v Value) NumField() int,  返回v持有的结构体类型值的字段数,如果v的Kind不是Struct会panic
    for i := 0; i < t.NumField(); i++ {
        data[t.Field(i).Name] = v.Field(i).Interface()
    }
    return data
}

//结构体转map方法2
func StructToMapViaJson(data S) map[string]interface{} {
    m := make(map[string]interface{})
    //struct 转json
    j, _ := json.Marshal(data)
    //json 转map
    json.Unmarshal(j, &m)
    return m
}

func FillStruct(data map[string]interface{}, obj interface{}) error {
    for k, v := range data {
        //fmt.Println("k: ", k, " v: ", v)
        err := SetField(obj, k, v)
        if err != nil {
            return err
        }
    }
    return nil
}

func SetField(obj interface{}, k string, v interface{}) error {
    //结构体属性值
    structValue := reflect.ValueOf(obj).Elem()
    //fmt.Println("structValue: ", structValue)
    //结构体单个属性值
    structFieldValue := structValue.FieldByName(k)
    //fmt.Println("structFieldValue: ", structFieldValue)
    if !structFieldValue.IsValid() {
        return fmt.Errorf("No such field: %s in obj", k)
    }
    if !structFieldValue.CanSet() {
        return fmt.Errorf("Cannot set %s field value", k)
    }
    //结构体属性类型
    structFieldType := structFieldValue.Type()
    val := reflect.ValueOf(v)
    var err error
    if structFieldType != val.Type() {
        //类型转换
        val, err = TypeConversion(fmt.Sprintf("%v", v), structFieldValue.Type().Name())
        if err != nil {
            return err
        }
    }
    structFieldValue.Set(val)
    return nil
}

func TypeConversion(value string, ntype string) (reflect.Value, error) {
    fmt.Println("call TypeConversion...")
    if ntype == "string" {
        return reflect.ValueOf(value), nil
    } else if ntype == "time.Time" {
        t, err := time.ParseInLocation("2006-01-02 15:04:05", value, time.Local)
        return reflect.ValueOf(t), err
    } else if ntype == "Time" {
        t, err := time.ParseInLocation("2006-01-02 15:04:05", value, time.Local)
        return reflect.ValueOf(t), err
    } else if ntype == "int" {
        i, err := strconv.Atoi(value)
        return reflect.ValueOf(i), err
    } else if ntype == "int8" {
        i, err := strconv.ParseInt(value, 10, 64)
        return reflect.ValueOf(int8(i)), err
    } else if ntype == "int32" {
        i, err := strconv.ParseInt(value, 10, 64)
        return reflect.ValueOf(int64(i)), err
    } else if ntype == "int64" {
        i, err := strconv.ParseInt(value, 10, 64)
        return reflect.ValueOf(i), err
    } else if ntype == "float32" {
        i, err := strconv.ParseFloat(value, 64)
        return reflect.ValueOf(float32(i)), err
    } else if ntype == "float64" {
        i, err := strconv.ParseFloat(value, 64)
        return reflect.ValueOf(i), err
    }

    //else if .......增加其他一些类型的转换

    return reflect.ValueOf(value), errors.New("未知的类型:" + ntype)
}

func main() {

    var s S
    Types := reflect.TypeOf(s)
    //TypeData.FieldByIndex([]int{}) 返回 StructField
    //[]int{}参数: 第一个是struct类型的索引(如果索引为参数一的数据类型不是struct会报错), 第二个是索引为参数一的结构体内属性的索引
    //例如[]int{0,0} 会输出[0] a string,表示索引为0的结构体User内索引为0的数据是a
    //[]int{0, 1} 会输出[1] b string
    //[]int{1, 0}会报错, 因为索引为1的数据是S结构体中的数据 Name string,数据类型不是struct
    res := Types.FieldByIndex([]int{0, 0})
    fmt.Println("FieldByIndex: ", res.Index, res.Name, res.Type)

    //struct to map
    info := S{Name: "xsk", Age: 22, Address: "shanghai"}
    data := Struct2Map(info)
    fmt.Println("data: ", data, "  ", "typeof(data): ", reflect.TypeOf(data))
    for k, v := range data {
        fmt.Println(k, v.(interface{}))
    }
    fmt.Println("---------")
    data1 := StructToMapViaJson(info)
    fmt.Println("data1: ", data1, "  ", "typeof(data1): ", reflect.TypeOf(data1))
    for k, v := range data1 {
        fmt.Println(k, v.(interface{}))
    }
    fmt.Println("---------")

    //map to struct
    data2 := make(map[string]interface{})
    data2["Name"] = "xsk"
    data2["Age"] = 22
    data2["Address"] = "shanghai"
    result := &S{}
    err := FillStruct(data2, result)
    fmt.Println("err: ", err, " result: ", fmt.Sprintf("%+v", *result))
    fmt.Println("---------")

    //map[string]*Struct 下面几种初始化都行
    //第一种
    //var info1 = map[string]*S{"info": &S{Name: "mtt", Age: 23, Address: "shanghai"}}
    //第二种
    var info1 = map[string]*S{"info": &S{}, "other": &S{}}
    info1["info"].Name = "mtt"
    info1["info"].Age = 23
    info1["info"].Address = "shanghai"

    fmt.Println("info1: ", *info1["info"])
    t := reflect.TypeOf(*info1["info"])
    v := reflect.ValueOf(*info1["info"])
    for k := 0; k < t.NumField(); k++ {
        fmt.Printf("%s: %v\n", t.Field(k).Name, v.Field(k).Interface())
    }
    fmt.Println("---------")

    //第三种
    var info2 = map[string]*S{}
    info2["info"] = &S{Name: "xly", Age: 1, Address: "shanghai"}
    fmt.Println("info2: ", *info2["info"])
    ty := reflect.TypeOf(*info2["info"])
    vl := reflect.ValueOf(*info2["info"])
    for k := 0; k < ty.NumField(); k++ {
        fmt.Printf("%s: %v\n", ty.Field(k).Name, vl.Field(k).Interface())
    }

}package main

import (
    "encoding/json"



你的当前访问异常,请进行认证后继续阅读剩余内容。

分享到: