当前位置: 首页 > news >正文

go mapstructure使用例子

展示mapstructure库的使用示例。这是一个非常实用的 Go 库,用于将map[string]interface{}解码到结构体。

基础用法

1. 简单解码

go

复制

package main import ( "fmt" "github.com/mitchellh/mapstructure" ) type Person struct { Name string Age int Email string } func main() { input := map[string]interface{}{ "name": "张三", "age": 25, "email": "zhangsan@example.com", } var person Person err := mapstructure.Decode(input, &person) if err != nil { panic(err) } fmt.Printf("%+v\n", person) // 输出: {Name:张三 Age:25 Email:zhangsan@example.com} }

2. 使用标签(Tags)

go

复制

type User struct { ID int64 `mapstructure:"user_id"` // 映射不同字段名 UserName string `mapstructure:"user_name"` Password string `mapstructure:"-"` // 忽略该字段 CreatedAt string `mapstructure:"created_at"` Tags []string `mapstructure:"tags"` Metadata map[string]string `mapstructure:"metadata"` } func main() { input := map[string]interface{}{ "user_id": 1001, "user_name": "admin", "password": "secret123", // 会被忽略 "created_at": "2024-01-15", "tags": []string{"vip", "active"}, "metadata": map[string]string{"ip": "192.168.1.1"}, } var user User if err := mapstructure.Decode(input, &user); err != nil { panic(err) } fmt.Printf("%+v\n", user) // 输出: {ID:1001 UserName:admin Password: CreatedAt:2024-01-15 Tags:[vip active] Metadata:map[ip:192.168.1.1]} }

高级用法

3. 嵌套结构体

go

复制

type Address struct { City string `mapstructure:"city"` Street string `mapstructure:"street"` ZipCode string `mapstructure:"zip_code"` } type Company struct { Name string `mapstructure:"name"` Address Address `mapstructure:"address"` // 嵌套结构体 Employees int `mapstructure:"employee_count"` } func main() { input := map[string]interface{}{ "name": "科技公司", "address": map[string]interface{}{ "city": "北京", "street": "中关村大街", "zip_code": "100080", }, "employee_count": 500, } var company Company if err := mapstructure.Decode(input, &company); err != nil { panic(err) } fmt.Printf("公司: %s, 城市: %s\n", company.Name, company.Address.City) // 输出: 公司: 科技公司, 城市: 北京 }

4. 弱类型转换(WeaklyTypedInput)

go

复制

type Config struct { Port int `mapstructure:"port"` Enabled bool `mapstructure:"enabled"` Timeout float64 `mapstructure:"timeout"` Hosts []string `mapstructure:"hosts"` } func main() { // 字符串自动转为对应类型 input := map[string]interface{}{ "port": "8080", // string -> int "enabled": "true", // string -> bool "timeout": "30.5", // string -> float64 "hosts": "host1,host2", // string -> []string (逗号分隔) } var config Config decoderConfig := &mapstructure.DecoderConfig{ WeaklyTypedInput: true, // 启用弱类型转换 Result: &config, } decoder, err := mapstructure.NewDecoder(decoderConfig) if err != nil { panic(err) } if err := decoder.Decode(input); err != nil { panic(err) } fmt.Printf("%+v\n", config) // 输出: {Port:8080 Enabled:true Timeout:30.5 Hosts:[host1 host2]} }

5. 使用 DecoderConfig 自定义解码

go

复制

type Event struct { ID int64 `mapstructure:"id"` Name string `mapstructure:"name"` Timestamp int64 `mapstructure:"timestamp"` } // 自定义解码钩子:处理时间戳 func StringToTimeHookFunc() mapstructure.DecodeHookFunc { return func( f reflect.Type, t reflect.Type, data interface{}, ) (interface{}, error) { // 将字符串时间转为 int64 时间戳 if f.Kind() != reflect.String { return data, nil } if t != reflect.TypeOf(int64(0)) { return data, nil } // 尝试解析时间字符串 layouts := []string{ "2006-01-02 15:04:05", "2006-01-02", time.RFC3339, } str := data.(string) for _, layout := range layouts { if t, err := time.Parse(layout, str); err == nil { return t.Unix(), nil } } return data, nil } } func main() { input := map[string]interface{}{ "id": 1, "name": "会议", "timestamp": "2024-01-15 10:30:00", // 字符串时间 } var event Event config := &mapstructure.DecoderConfig{ DecodeHook: mapstructure.ComposeDecodeHookFunc( StringToTimeHookFunc(), mapstructure.StringToSliceHookFunc(","), ), WeaklyTypedInput: true, Result: &event, } decoder, _ := mapstructure.NewDecoder(config) if err := decoder.Decode(input); err != nil { panic(err) } fmt.Printf("事件: %s, 时间戳: %d\n", event.Name, event.Timestamp) }

实际应用场景

6. JSON 动态字段处理

go

复制

// API 响应处理 type APIResponse struct { Code int `mapstructure:"code"` Message string `mapstructure:"message"` Data map[string]interface{} `mapstructure:"data"` // 动态数据 } type UserDetail struct { ID int64 `mapstructure:"id"` Username string `mapstructure:"username"` Avatar string `mapstructure:"avatar"` } func ParseAPIResponse(respJSON []byte) (*UserDetail, error) { var apiResp APIResponse if err := json.Unmarshal(respJSON, &apiResp); err != nil { return nil, err } if apiResp.Code != 200 { return nil, fmt.Errorf("API错误: %s", apiResp.Message) } var user UserDetail if err := mapstructure.Decode(apiResp.Data, &user); err != nil { return nil, err } return &user, nil }

7. 配置文件解析(配合 viper)

go

复制

// config.yaml // server: // host: "0.0.0.0" // port: 8080 // database: // driver: "mysql" // dsn: "user:pass@tcp(localhost:3306)/db" type ServerConfig struct { Host string `mapstructure:"host"` Port int `mapstructure:"port"` } type DBConfig struct { Driver string `mapstructure:"driver"` DSN string `mapstructure:"dsn"` } type Config struct { Server ServerConfig `mapstructure:"server"` Database DBConfig `mapstructure:"database"` } func LoadConfig(path string) (*Config, error) { viper.SetConfigFile(path) if err := viper.ReadInConfig(); err != nil { return nil, err } var config Config // viper 内部使用 mapstructure if err := viper.Unmarshal(&config); err != nil { return nil, err } return &config, nil }

8. 数据库查询结果映射

go

复制

// 将 SQL 查询结果(map)转为结构体 func QueryUser(db *sql.DB, id int64) (*User, error) { rows, err := db.Query("SELECT id, user_name, created_at FROM users WHERE id = ?", id) if err != nil { return nil, err } defer rows.Close() columns, _ := rows.Columns() var result map[string]interface{} for rows.Next() { values := make([]interface{}, len(columns)) valuePtrs := make([]interface{}, len(columns)) for i := range columns { valuePtrs[i] = &values[i] } if err := rows.Scan(valuePtrs...); err != nil { return nil, err } result = make(map[string]interface{}) for i, col := range columns { result[col] = values[i] } } var user User if err := mapstructure.Decode(result, &user); err != nil { return nil, err } return &user, nil }

错误处理与调试

go

复制

// 收集解码错误 type Product struct { ID int64 `mapstructure:"id"` Name string `mapstructure:"name"` Price float64 `mapstructure:"price"` Stock int `mapstructure:"stock"` } func main() { input := map[string]interface{}{ "id": "not-a-number", // 类型错误 "name": "商品A", "price": "invalid", // 类型错误 "stock": 100, } var product Product decoderConfig := &mapstructure.DecoderConfig{ Result: &product, WeaklyTypedInput: true, ErrorUnused: true, // 报告未使用的字段 Metadata: &mapstructure.Metadata{}, // 收集元数据 } decoder, _ := mapstructure.NewDecoder(decoderConfig) err := decoder.Decode(input) if err != nil { fmt.Printf("解码错误: %v\n", err) } // 查看哪些字段未匹配 fmt.Printf("未使用的键: %v\n", decoderConfig.Metadata.Unused) fmt.Printf("已解码的键: %v\n", decoderConfig.Metadata.Keys) }

关键特性总结

表格

复制

特性说明
mapstructure:"field_name"指定映射的字段名
mapstructure:"-"忽略该字段
WeaklyTypedInput启用弱类型转换(string→int等)
DecodeHook自定义解码逻辑
ErrorUnused报错当 map 中有未使用的字段
Metadata收集解码过程的元数据
Squash嵌入结构体扁平化(匿名嵌套)

mapstructure特别适合处理动态数据(JSON、YAML、数据库结果集、表单数据等)到强类型结构体的转换,是 Go 项目中非常实用的工具库。

http://www.jsqmd.com/news/377661/

相关文章:

  • 硬币找零问题的动态规划解法与实现思考笔记
  • TPJ系列机械式螺旋圆弹簧疲劳试验机
  • 2026年市场评价好的包装袋定制厂家选哪家,四边封包装袋/自立袋/聚酯尼龙袋/三边封拉链袋,包装袋制造厂家推荐排行 - 品牌推荐师
  • 【Python毕设全套源码+文档】基于python的媒体资源管理系统的设计与实现(丰富项目+远程调试+讲解+定制)
  • 『NAS』设置内网固定 IP
  • 教你如何识别台式电脑电源的好坏
  • 【Python毕设全套源码+文档】基于python的采用人脸识别技术的课堂考勤管理系统的设计与实现(丰富项目+远程调试+讲解+定制)
  • 面试必看:打家劫舍
  • 2026年工业研学公司综合评测:聚焦科创实践与产教融合的新趋势​ - 品牌2025
  • 【Python毕设全套源码+文档】基于python的租房管理系统的设计与实现(丰富项目+远程调试+讲解+定制)
  • 56周作业
  • 2026年工业焊接协作机器人知名品牌商选择指南,推荐上海广为 - 品牌2025
  • comsol多孔介质流燃烧器模型,集层流流动模块,流体传热模块,浓物质传递模块和化学反应模块于...
  • 50.k8s管理-1和 k8s核心概述-2 - 实践
  • 【Python毕设全套源码+文档】基于python的个人身心健康管理系统的设计与实现(丰富项目+远程调试+讲解+定制)
  • 2026年全国防爆墙厂家哪家靠谱?靠谱优质实力强劲 适配多场景防护需求 覆盖全国多区域需求 - 深度智识库
  • 车桥耦合Matlab程序:Newmark法数值积分实现动力学求解
  • AT_agc013_d [AGC013D] Piling Up
  • 2026年汽车应急启动电源十大品牌推荐深度解析 - 品牌2025
  • 那些年我们create generate clock遇到的坑
  • 武商一卡通使用与回收:超实用指南让你轻松搞定 - 团团收购物卡回收
  • 2026年优选五大汽车电瓶设备公司选择指南 - 品牌2025
  • 2026年汽车电瓶设备出口公司推荐:全球市场中的中国智造力量 - 品牌2025
  • 详细介绍:D3.js研发交互模型指标柱形图
  • 售后完善的架空保温管价格如何,怎么选购 - mypinpai
  • 毕业论文神器!9个AI论文软件深度测评,本科生高效写作必备
  • 【python毕设源码分享】基于Python的个人身心健康管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 剖析实力强的氟橡胶制品,江苏衡水联奥橡塑获客户认可 - 工业品牌热点
  • 91.不同路径
  • 2026年开放大学排名,湖北开放大学监考严格吗 - 工业品网