mapstructure公开了将一种任意Go类型转换为另一种Go类型的功能
地址:https://github.com/mitchellh/mapstructure
文档:https://godoc.org/github.com/mitchellh/mapstructure
ps:viper 使用了该包

包函数

func Decode(input interface{}, output interface{}) error deep copy

type Decoder

decoder 是一个自定义得解码器,可以提供更多得功能,但不常用

  1. type Decoder struct {
  2. // contains filtered or unexported fields
  3. }

func NewDecoder(config DecoderConfig) (Decoder, error)
func (d *Decoder) Decode(input interface{}) error deep copy

type DecoderConfig

DecoderConfig是用于创建新解码器并允许定制解码的各个方面的配置

  1. type DecoderConfig struct {
  2. // 钩子函数
  3. DecodeHook DecodeHookFunc
  4. // 如果errorusage为true,如果一个键没使用,会报错
  5. ErrorUnused bool
  6. // 如果设置为真,将在写入字段之前将它们归零
  7. // 例如,在输入解码值之前,映射将被清空。如果这是假的,一个映射将被合并
  8. ZeroFields bool
  9. // 类型转换
  10. // "weak" conversions:
  11. //
  12. // - bools to string (true = "1", false = "0")
  13. // - numbers to string (base 10)
  14. // - bools to int/uint (true = 1, false = 0)
  15. // - strings to int/uint (base implied by prefix)
  16. // - int to bool (true if value != 0)
  17. // - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F,
  18. // FALSE, false, False. Anything else is an error)
  19. // - empty array = empty map and vice versa
  20. // - negative numbers to overflowed uint values (base 10)
  21. // - slice of maps to a merged map
  22. // - single values are converted to slices if required. Each
  23. // element is weakly decoded. For example: "4" can become []int{4}
  24. // if the target type is an int slice.
  25. //
  26. WeaklyTypedInput bool
  27. // Squash will squash embedded structs. A squash tag may also be
  28. // added to an individual struct field using a tag. For example:
  29. //
  30. // type Parent struct {
  31. // Child `mapstructure:",squash"`
  32. // }
  33. Squash bool
  34. // 元数据是将包含关于的额外元数据的结构解码。如果该值为nil,则不跟踪元数据。
  35. Metadata *Metadata
  36. // 结果
  37. Result interface{}
  38. // mapstructure读取字段名的标记名。默认为“mapstructure”
  39. TagName string
  40. }

type DecodeHookFunc

  1. type DecodeHookFunc interface{}

func ComposeDecodeHookFunc(fs …DecodeHookFunc) DecodeHookFunc 将多个钩子合并
func StringToIPHookFunc() DecodeHookFunc 将字符串转换为net.IP的钩子
func StringToIPNetHookFunc() DecodeHookFunc 将字符串转换为net.IPNet的钩子
func StringToSliceHookFunc(sep string) DecodeHookFunc 通过seq将字符串转为切片
func StringToTimeDurationHookFunc() DecodeHookFunc 将字符串转为time.Time类型
func StringToTimeHookFunc(layout string) DecodeHookFunc 将字符串按layout格式转为time.Time类型

type Metadata

  1. type Metadata struct {
  2. // 成功解码的key集合
  3. Keys []string
  4. // 在原始内容中有,但目标源中未定义,导致没解码的key集合
  5. Unused []string
  6. }

例子

map转struct

  1. type Person struct {
  2. Name string
  3. Age int
  4. Emails []string
  5. Extra map[string]string
  6. }
  7. input := map[string]interface{}{
  8. "name": "Mitchell",
  9. "age": 91,
  10. "emails": []string{"one", "two", "three"},
  11. "extra": map[string]string{
  12. "twitter": "mitchellh",
  13. },
  14. }
  15. var result Person
  16. err := Decode(input, &result)
  17. if err != nil {
  18. panic(err)
  19. }
  20. fmt.Printf("%#v", result)
  21. mapstructure.Person{Name:"Mitchell", Age:91, Emails:[]string{"one", "two", "three"}, Extra:map[string]string{"twitter":"mitchellh"}}

struct转map

  1. type User struct {
  2. Name string
  3. Age int
  4. }
  5. func main2() {
  6. u1 := User{"zhangsan", 20}
  7. var result map[string]interface{}
  8. err := mapstructure.Decode(u1, &result)
  9. if err != nil {
  10. panic(err)
  11. }
  12. fmt.Printf("%+v", result) // map[Age:20 Name:zhangsan]
  13. }

slice map 转 slice struct

  1. type Person1 struct {
  2. Name string
  3. Age int
  4. Emails []string
  5. Extra map[string]string
  6. }
  7. func main() {
  8. input1 := map[string]interface{}{
  9. "name": "input1",
  10. "age": 91,
  11. "emails": []string{"one", "two", "three"},
  12. "extra": map[string]string{
  13. "twitter": "mitchellh",
  14. },
  15. }
  16. input2 := map[string]interface{}{
  17. "name": "input2",
  18. "age": 91,
  19. "emails": []string{"one", "two", "three"},
  20. "extra": map[string]string{
  21. "twitter": "mitchellh",
  22. },
  23. }
  24. input := []map[string]interface{}{input1, input2}
  25. var result []Person1
  26. err := mapstructure.Decode(input, &result)
  27. if err != nil {
  28. panic(err)
  29. }
  30. fmt.Printf("%v", result)
  31. }
  32. [{input1 91 [one two three] map[twitter:mitchellh]}
  33. {input2 91 [one two three] map[twitter:mitchellh]}]

slice struct 转 slice struct

  1. type User1 struct {
  2. Name string
  3. Age int
  4. }
  5. type User2 struct {
  6. UName string `mapstructure:"name"` // 首字母的大小写不受影响
  7. uAddr string
  8. UAge int `mapstructure:"Age"` // 首字母的大小写不受影响
  9. }
  10. func main() {
  11. u1 := []User1{
  12. {"zhangsan1", 20},
  13. {"zhangsan2", 30},
  14. }
  15. var result []User2
  16. err := mapstructure.Decode(u1, &result)
  17. if err != nil {
  18. panic(err)
  19. }
  20. fmt.Printf("%+v", result) // [{UName:zhangsan1 uAddr: UAge:20} {UName:zhangsan2 uAddr: UAge:30}]
  21. }

struct转struct(类型一致)

  1. type User struct {
  2. Name string
  3. Age int
  4. }
  5. type User2 struct {
  6. UName string `mapstructure:"name"` // 首字母的大小写不受影响
  7. uAddr string
  8. UAge int `mapstructure:"Age"` // 首字母的大小写不受影响
  9. }
  10. func main() {
  11. u1 := User{"zhangsan", 20}
  12. var result User2
  13. err := mapstructure.Decode(u1, &result)
  14. if err != nil {
  15. panic(err)
  16. }
  17. fmt.Printf("%+v", result) // {UName:zhangsan uAddr: UAge:20}
  18. }

struct转struct(类型不一致)

  1. type User struct {
  2. Name string
  3. Age int
  4. }
  5. type User3 struct {
  6. UName string `mapstructure:"name"`
  7. uAddr string
  8. UAge string `mapstructure:"Age"`
  9. }
  10. func main() {
  11. u1 := User{"zhangsan", 20}
  12. var result User3
  13. config := &mapstructure.DecoderConfig{
  14. WeaklyTypedInput: true,
  15. Result: &result,
  16. }
  17. decoder, err := mapstructure.NewDecoder(config)
  18. if err != nil {
  19. panic(err)
  20. }
  21. err = decoder.Decode(u1)
  22. if err != nil {
  23. panic(err)
  24. }
  25. fmt.Printf("%+v", result) // {UName:zhangsan uAddr: UAge:20}
  26. }

Metadata

  1. type Person struct {
  2. Name string
  3. Age int
  4. }
  5. input := map[string]interface{}{
  6. "name": "Mitchell",
  7. "age": 91,
  8. "email": "foo@bar.com",
  9. }
  10. var md Metadata
  11. var result Person
  12. config := &DecoderConfig{
  13. Metadata: &md,
  14. Result: &result,
  15. }
  16. decoder, err := NewDecoder(config)
  17. if err != nil {
  18. panic(err)
  19. }
  20. if err := decoder.Decode(input); err != nil {
  21. panic(err)
  22. }
  23. fmt.Printf("Unused keys: %#v", md.Unused) // Unused keys: []string{"email"}