背景
我们在前面介绍过怎么使用net/http
发送json或者map数据,那么它能不能直接发送结构体数据呢?我们今天一起来学习结构体struct转map的三种方法,为后续做铺垫。
struct转map
使用json模块
直接使用json.Marshal
方法来强制转化struct。
参考代码:
func JSONMethod(content interface{}) map[string]interface{} { var name map[string]interface{} if marshalContent, err := json.Marshal(content); err != nil { fmt.Println(err) } else { d := json.NewDecoder(bytes.NewReader(marshalContent)) d.UseNumber() // 设置将float64转为一个number if err := d.Decode(&name); err != nil { fmt.Println(err) } else { for k, v := range name { name[k] = v } } } return name}
使用reflect模块
通过reflect模块来获取结构体的key值和value值,然后直接进行组装。这种方法不能识别结构体中的tag,所以无法兼容首字母小写,而其他字母存在大写的情况.
参考代码:func ReflectMethod(obj interface{}) map[string]interface{} { t := reflect.TypeOf(obj) v := reflect.ValueOf(obj) var data = make(map[string]interface{}) for i := 0; i < t.NumField(); i++ { data[strings.ToLower(t.Field(i).Name)] = v.Field(i).Interface() } return data}
使用第三方库
第三种方法是使用第三方库github.com/fatih/structs
,他提供了比较丰富的函数,让我们可以像python中一样轻松的获取所有的key值(structs.Names(server)),所有的value值(structs.Values(server)),甚至直接进行类型判断(structs.IsZero(server))等等。
更详细的信息可以查阅:
测试
type Human struct { Name string `json:"name"` Age int `json:"age"` Profile string `structs:"profile"` IsGopher bool `json:"isGopher"`}func main() { human := Human{"Detector", 18, "A tester", true} fmt.Println("Json method:", JSONMethod(human)) fmt.Println("========") fmt.Println("Reflect method:", ReflectMethod(human)) fmt.Println("========") fmt.Println("Third lb:", structs.Map(human))}
输出如下:
总结
从测试结果可以看到,三种方式都能完成struct转map,但是reflect方法无法识别结构体中的tag,第三方库只能使用tag structs
,所以如果考虑兼容性(考虑到协同开发)和尽量使用官方库的原则,推荐使用第一种方法(json转换)。
- reflect.Field
- json
- structs