结构体转map[string]interface{}
1、JSON序列化方式
1 2 3 4 5 6 7 8 9 10 | func main() { u1 := UserInfo{Name: "q1mi" , Age: 18} b, _ := json.Marshal(&u1) var m map [string] interface {} _ = json.Unmarshal(b, &m) for k, v := range m{ fmt.Printf( "key:%v value:%v\n" , k, v) } } |
注意:这种方法有个缺点,那就是Go语言中的json
包在序列化空接口存放的数字类型(整型、浮点型等)都会序列化成float64类型。
2、反射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // ToMap 结构体转为Map[string]interface{} func ToMap(in interface {}, tagName string) ( map [string] interface {}, error){ out := make( map [string] interface {}) v := reflect.ValueOf(in) if v.Kind() == reflect.Ptr { v = v.Elem() } if v.Kind() != reflect.Struct { // 非结构体返回错误提示 return nil, fmt.Errorf( "ToMap only accepts struct or struct pointer; got %T" , v) } t := v.Type() // 遍历结构体字段 // 指定tagName值为map中key;字段值为map中value for i := 0; i < v.NumField(); i++ { fi := t.Field(i) if tagValue := fi.Tag.Get(tagName); tagValue != "" { out[tagValue] = v.Field(i).Interface() } } return out, nil } |
3、第三方库structs
Github上也有现成的轮子,例如第三方库:https://github.com/fatih/structs。它使用的自定义结构体tag是structs
:
1 2 3 4 5 6 7 8 9 10 | // UserInfo 用户信息 type UserInfo struct { Name string `json: "name" structs: "name" ` Age int `json: "age" structs: "age" ` } m3 := structs.Map(&u1) for k, v := range m3 { fmt.Printf( "key:%v value:%v value type:%T\n" , k, v, v) } |
4、嵌套结构体转map[string]interface{}
1)structs
本身是支持嵌套结构体转map[string]interface{}
的,遇到结构体嵌套它会转换为map[string]interface{}
嵌套map[string]interface{}
的模式。
2)使用反射转成单层map
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | // ToMap2 将结构体转为单层map func ToMap2(in interface {}, tag string) ( map [string] interface {}, error) { // 当前函数只接收struct类型 v := reflect.ValueOf(in) if v.Kind() == reflect.Ptr { // 结构体指针 v = v.Elem() } if v.Kind() != reflect.Struct { return nil, fmt.Errorf( "ToMap only accepts struct or struct pointer; got %T" , v) } out := make( map [string] interface {}) queue := make([] interface {}, 0, 1) queue = append(queue, in) for len(queue) > 0 { v := reflect.ValueOf(queue[0]) if v.Kind() == reflect.Ptr { // 结构体指针 v = v.Elem() } queue = queue[1:] t := v.Type() for i := 0; i < v.NumField(); i++ { vi := v.Field(i) if vi.Kind() == reflect.Ptr { // 内嵌指针 vi = vi.Elem() if vi.Kind() == reflect.Struct { // 结构体 queue = append(queue, vi.Interface()) } else { ti := t.Field(i) if tagValue := ti.Tag.Get(tag); tagValue != "" { // 存入map out[tagValue] = vi.Interface() } } break } if vi.Kind() == reflect.Struct { // 内嵌结构体 queue = append(queue, vi.Interface()) break } // 一般字段 ti := t.Field(i) if tagValue := ti.Tag.Get(tag); tagValue != "" { // 存入map out[tagValue] = vi.Interface() } } } return out, nil } |
参考:结构体转map[string]interface{}的若干方法 | 李文周的博客 (liwenzhou.com)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码