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 是一个自定义得解码器,可以提供更多得功能,但不常用
type Decoder struct {
// contains filtered or unexported fields
}
func NewDecoder(config DecoderConfig) (Decoder, error)
func (d *Decoder) Decode(input interface{}) error deep copy
type DecoderConfig
DecoderConfig是用于创建新解码器并允许定制解码的各个方面的配置
type DecoderConfig struct {
// 钩子函数
DecodeHook DecodeHookFunc
// 如果errorusage为true,如果一个键没使用,会报错
ErrorUnused bool
// 如果设置为真,将在写入字段之前将它们归零
// 例如,在输入解码值之前,映射将被清空。如果这是假的,一个映射将被合并
ZeroFields bool
// 类型转换
// "weak" conversions:
//
// - bools to string (true = "1", false = "0")
// - numbers to string (base 10)
// - bools to int/uint (true = 1, false = 0)
// - strings to int/uint (base implied by prefix)
// - int to bool (true if value != 0)
// - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F,
// FALSE, false, False. Anything else is an error)
// - empty array = empty map and vice versa
// - negative numbers to overflowed uint values (base 10)
// - slice of maps to a merged map
// - single values are converted to slices if required. Each
// element is weakly decoded. For example: "4" can become []int{4}
// if the target type is an int slice.
//
WeaklyTypedInput bool
// Squash will squash embedded structs. A squash tag may also be
// added to an individual struct field using a tag. For example:
//
// type Parent struct {
// Child `mapstructure:",squash"`
// }
Squash bool
// 元数据是将包含关于的额外元数据的结构解码。如果该值为nil,则不跟踪元数据。
Metadata *Metadata
// 结果
Result interface{}
// mapstructure读取字段名的标记名。默认为“mapstructure”
TagName string
}
type DecodeHookFunc
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
type Metadata struct {
// 成功解码的key集合
Keys []string
// 在原始内容中有,但目标源中未定义,导致没解码的key集合
Unused []string
}
例子
map转struct
type Person struct {
Name string
Age int
Emails []string
Extra map[string]string
}
input := map[string]interface{}{
"name": "Mitchell",
"age": 91,
"emails": []string{"one", "two", "three"},
"extra": map[string]string{
"twitter": "mitchellh",
},
}
var result Person
err := Decode(input, &result)
if err != nil {
panic(err)
}
fmt.Printf("%#v", result)
mapstructure.Person{Name:"Mitchell", Age:91, Emails:[]string{"one", "two", "three"}, Extra:map[string]string{"twitter":"mitchellh"}}
struct转map
type User struct {
Name string
Age int
}
func main2() {
u1 := User{"zhangsan", 20}
var result map[string]interface{}
err := mapstructure.Decode(u1, &result)
if err != nil {
panic(err)
}
fmt.Printf("%+v", result) // map[Age:20 Name:zhangsan]
}
slice map 转 slice struct
type Person1 struct {
Name string
Age int
Emails []string
Extra map[string]string
}
func main() {
input1 := map[string]interface{}{
"name": "input1",
"age": 91,
"emails": []string{"one", "two", "three"},
"extra": map[string]string{
"twitter": "mitchellh",
},
}
input2 := map[string]interface{}{
"name": "input2",
"age": 91,
"emails": []string{"one", "two", "three"},
"extra": map[string]string{
"twitter": "mitchellh",
},
}
input := []map[string]interface{}{input1, input2}
var result []Person1
err := mapstructure.Decode(input, &result)
if err != nil {
panic(err)
}
fmt.Printf("%v", result)
}
[{input1 91 [one two three] map[twitter:mitchellh]}
{input2 91 [one two three] map[twitter:mitchellh]}]
slice struct 转 slice struct
type User1 struct {
Name string
Age int
}
type User2 struct {
UName string `mapstructure:"name"` // 首字母的大小写不受影响
uAddr string
UAge int `mapstructure:"Age"` // 首字母的大小写不受影响
}
func main() {
u1 := []User1{
{"zhangsan1", 20},
{"zhangsan2", 30},
}
var result []User2
err := mapstructure.Decode(u1, &result)
if err != nil {
panic(err)
}
fmt.Printf("%+v", result) // [{UName:zhangsan1 uAddr: UAge:20} {UName:zhangsan2 uAddr: UAge:30}]
}
struct转struct(类型一致)
type User struct {
Name string
Age int
}
type User2 struct {
UName string `mapstructure:"name"` // 首字母的大小写不受影响
uAddr string
UAge int `mapstructure:"Age"` // 首字母的大小写不受影响
}
func main() {
u1 := User{"zhangsan", 20}
var result User2
err := mapstructure.Decode(u1, &result)
if err != nil {
panic(err)
}
fmt.Printf("%+v", result) // {UName:zhangsan uAddr: UAge:20}
}
struct转struct(类型不一致)
type User struct {
Name string
Age int
}
type User3 struct {
UName string `mapstructure:"name"`
uAddr string
UAge string `mapstructure:"Age"`
}
func main() {
u1 := User{"zhangsan", 20}
var result User3
config := &mapstructure.DecoderConfig{
WeaklyTypedInput: true,
Result: &result,
}
decoder, err := mapstructure.NewDecoder(config)
if err != nil {
panic(err)
}
err = decoder.Decode(u1)
if err != nil {
panic(err)
}
fmt.Printf("%+v", result) // {UName:zhangsan uAddr: UAge:20}
}
Metadata
type Person struct {
Name string
Age int
}
input := map[string]interface{}{
"name": "Mitchell",
"age": 91,
"email": "foo@bar.com",
}
var md Metadata
var result Person
config := &DecoderConfig{
Metadata: &md,
Result: &result,
}
decoder, err := NewDecoder(config)
if err != nil {
panic(err)
}
if err := decoder.Decode(input); err != nil {
panic(err)
}
fmt.Printf("Unused keys: %#v", md.Unused) // Unused keys: []string{"email"}