内容简介:文章来源:使用方式:
文章来源: https://gfer.me/util/gconv/index
gf
框架提供了非常强大的类型转换包 gconv
,可以实现将任何数据类型转换为指定的数据类型,对常用基本数据类型之间的无缝转换,同时也支持任意类型到 struct
对象的属性赋值。由于 gconv
模块内部大量使用了断言而非反射(仅 struct
转换使用到了反射),因此执行的效率非常高。
使用方式:
import "gitee.com/johng/gf/g/util/gconv"
方法列表: godoc.org/github.com/johng-cn/gf/g/util/gconv
// 基本类型 func Bool(i interface{}) bool func Float32(i interface{}) float32 func Float64(i interface{}) float64 func Int(i interface{}) int func Int16(i interface{}) int16 func Int32(i interface{}) int32 func Int64(i interface{}) int64 func Int8(i interface{}) int8 func String(i interface{}) string func Uint(i interface{}) uint func Uint16(i interface{}) uint16 func Uint32(i interface{}) uint32 func Uint64(i interface{}) uint64 func Uint8(i interface{}) uint8 // slice类型 func Bytes(i interface{}) []byte func Ints(i interface{}) []int func Floats(i interface{}) []float64 func Strings(i interface{}) []string func Interfaces(i interface{}) []interface{} // 时间类型 func Time(i interface{}, format ...string) time.Time func TimeDuration(i interface{}) time.Duration // 对象转换 func Struct(params interface{}, objPointer interface{}, attrMapping ...map[string]string) error // 根据类型名称执行基本类型转换(非struct转换)) func Convert(i interface{}, t string, extraParams ...interface{}) interface{}
基本使用
常用基本类型的转换方法比较简单,我们这里使用一个例子来演示转换方法的使用及效果。
package main import ( "fmt" "gitee.com/johng/gf/g/util/gconv" ) func main() { i := 123 fmt.Printf("%10s %v\n", "Int:", gconv.Int(i)) fmt.Printf("%10s %v\n", "Int8:", gconv.Int8(i)) fmt.Printf("%10s %v\n", "Int16:", gconv.Int16(i)) fmt.Printf("%10s %v\n", "Int32:", gconv.Int32(i)) fmt.Printf("%10s %v\n", "Int64:", gconv.Int64(i)) fmt.Printf("%10s %v\n", "Uint:", gconv.Uint(i)) fmt.Printf("%10s %v\n", "Uint8:", gconv.Uint8(i)) fmt.Printf("%10s %v\n", "Uint16:", gconv.Uint16(i)) fmt.Printf("%10s %v\n", "Uint32:", gconv.Uint32(i)) fmt.Printf("%10s %v\n", "Uint64:", gconv.Uint64(i)) fmt.Printf("%10s %v\n", "Float32:", gconv.Float32(i)) fmt.Printf("%10s %v\n", "Float64:", gconv.Float64(i)) fmt.Printf("%10s %v\n", "Bool:", gconv.Bool(i)) fmt.Printf("%10s %v\n", "String:", gconv.String(i)) fmt.Printf("%10s %v\n", "Bytes:", gconv.Bytes(i)) fmt.Printf("%10s %v\n", "Strings:", gconv.Strings(i)) fmt.Printf("%10s %v\n", "Ints:", gconv.Ints(i)) fmt.Printf("%10s %v\n", "Floats:", gconv.Floats(i)) fmt.Printf("%10s %v\n", "Interfaces:", gconv.Interfaces(i)) }
执行后,输出结果为:
Int: 123 Int8: 123 Int16: 123 Int32: 123 Int64: 123 Uint: 123 Uint8: 123 Uint16: 123 Uint32: 123 Uint64: 123 Float32: 123 Float64: 123 Bool: true String: 123 Bytes: [123] Strings: [123] Ints: [123] Floats: [123] Interfaces: [123]
Struct转换
项目中我们经常会遇到大量struct的使用,以及各种数据类型到struct的转换/赋值(特别是 json
/ xml
/各种协议编码转换的时候)。为提高编码及项目维护效率, gconv
模块为各位开发者带来了极大的福利,为数据解析提供了更高的灵活度。
gconv
模块执行 struct
转换的方法仅有一个,定义如下:
func Struct(params interface{}, objPointer interface{}, attrMapping ...map[string]string) error
其中:
-
params
为需要转换到struct
的变量参数,可以为任意数据类型,常见的数据类型为map
; -
objPointer
为需要执行转的目标struct
对象,这个参数必须为该struct
的对象指针,转换成功后该对象的属性将会更新; -
attrMapping
为自定义的map键名
到strcut属性
之间的映射关系,此时params
参数必须为map类型,否则该参数无意义;
转换规则
gconv
模块的 struct
转换特性非常强大,支持任意数据类型到 struct
属性的映射转换。在没有提供自定义 attrMapping
转换规则的情况下,默认的转换规则如下:
-
struct
中需要匹配的属性必须为公开属性
(首字母大小); -
根据
params
类型的不同,逻辑会有不同:-
params
参数为map
: 键名会自动按照不区分大小写
的形式与struct
属性进行匹配; -
params
参数为其他类型: 将会把该变量值与struct
的第一个属性进行匹配; -
此外,如果
struct
的属性为复杂数据类型如slice
,map
,strcut
那么会进行递归匹配赋值;
-
- 如果匹配成功,那么将键值赋值给属性,如果无法匹配,那么忽略;
以下是几个匹配的示例:
map键名 struct属性 是否匹配 name Name match Email Email match nickname NickName match NICKNAME NickName match Nick-Name NickName not match nick_name NickName not match nick_name Nick_Name match
示例1,基本使用
package main import ( "fmt" "gitee.com/johng/gf/g" "gitee.com/johng/gf/g/util/gconv" ) type User struct { Uid int Name string Pass1 string `gconv:"password1"` Pass2 string `gconv:"password2"` } func main() { user := (*User)(nil) // 使用默认映射规则绑定属性值到对象 user = new(User) params1 := g.Map{ "uid" : 1, "Name" : "john", "PASS1" : "123", "PaSs2" : "456", } if err := gconv.Struct(params1, user); err == nil { fmt.Println(user) } // 使用struct tag映射绑定属性值到对象 user = new(User) params2 := g.Map { "uid" : 2, "name" : "smith", "password1" : "111", "password2" : "222", } if err := gconv.Struct(params2, user); err == nil { fmt.Println(user) } }
可以看到,我们可以直接通过 Struct
方法将map按照默认规则绑定到struct上,也可以使用 struct tag
的方式进行灵活的设置。此外, Struct
方法有第三个map参数,用于指定自定义的参数名称到属性名称的映射关系。
执行后,输出结果为:
&{1 john 123 456} &{2 smith 111 222}
示例2,复杂类型转换
1. slice基本类型属性
package main import ( "gitee.com/johng/gf/g/util/gconv" "gitee.com/johng/gf/g" "fmt" ) // 演示slice类型属性的赋值 func main() { type User struct { Scores []int } user := new(User) scores := []interface{}{99, 100, 60, 140} // 通过map映射转换 if err := gconv.Struct(g.Map{"Scores" : scores}, user); err != nil { fmt.Println(err) } else { g.Dump(user) } // 通过变量映射转换,直接slice赋值 if err := gconv.Struct(scores, user); err != nil { fmt.Println(err) } else { g.Dump(user) } }
执行后,输出结果为:
{ "Scores": [ 99, 100, 60, 140 ] } { "Scores": [ 99, 100, 60, 140 ] }
2. struct属性为struct
package main import ( "gitee.com/johng/gf/g/util/gconv" "gitee.com/johng/gf/g" "fmt" ) func main() { type Score struct { Name string Result int } type User struct { Scores Score } user := new(User) scores := map[string]interface{}{ "Scores" : map[string]interface{}{ "Name" : "john", "Result" : 100, }, } // 嵌套struct转换 if err := gconv.Struct(scores, user); err != nil { fmt.Println(err) } else { g.Dump(user) } }
执行后,输出结果为:
{ "Scores": { "Name": "john", "Result": 100 } }
3. struct属性为slice,数值为slice
package main import ( "gitee.com/johng/gf/g/util/gconv" "gitee.com/johng/gf/g" "fmt" ) func main() { type Score struct { Name string Result int } type User struct { Scores []Score } user := new(User) scores := map[string]interface{}{ "Scores" : []interface{}{ map[string]interface{}{ "Name" : "john", "Result" : 100, }, map[string]interface{}{ "Name" : "smith", "Result" : 60, }, }, } // 嵌套struct转换,属性为slice类型,数值为slice map类型 if err := gconv.Struct(scores, user); err != nil { fmt.Println(err) } else { g.Dump(user) } }
执行后,输出结果为:
{ "Scores": [ { "Name": "john", "Result": 100 }, { "Name": "smith", "Result": 60 } ] }
4. struct属性为slice,数值为非slice
package main import ( "gitee.com/johng/gf/g/util/gconv" "gitee.com/johng/gf/g" "fmt" ) func main() { type Score struct { Name string Result int } type User struct { Scores []Score } user := new(User) scores := map[string]interface{}{ "Scores" : map[string]interface{}{ "Name" : "john", "Result" : 100, }, } // 嵌套struct转换,属性为slice类型,数值为map类型 if err := gconv.Struct(scores, user); err != nil { fmt.Println(err) } else { g.Dump(user) } }
执行后,输出结果为:
{ "Scores": [ { "Name": "john", "Result": 100 } ] }
基准性能测试
测试转换变量值为 123456789
,类型 int
。
john@john-B85M:~/Workspace/Go/GOPATH/src/gitee.com/johng/gf/g/util/gconv$ go test *.go -bench=".*" -benchmem goos: linux goarch: amd64 BenchmarkString-4 20000000 71.8 ns/op 24 B/op 2 allocs/op BenchmarkInt-4 100000000 22.2 ns/op 8 B/op 1 allocs/op BenchmarkInt8-4 100000000 24.5 ns/op 8 B/op 1 allocs/op BenchmarkInt16-4 50000000 23.8 ns/op 8 B/op 1 allocs/op BenchmarkInt32-4 100000000 24.1 ns/op 8 B/op 1 allocs/op BenchmarkInt64-4 100000000 21.7 ns/op 8 B/op 1 allocs/op BenchmarkUint-4 100000000 22.2 ns/op 8 B/op 1 allocs/op BenchmarkUint8-4 50000000 25.6 ns/op 8 B/op 1 allocs/op BenchmarkUint16-4 50000000 32.1 ns/op 8 B/op 1 allocs/op BenchmarkUint32-4 50000000 27.7 ns/op 8 B/op 1 allocs/op BenchmarkUint64-4 50000000 28.1 ns/op 8 B/op 1 allocs/op BenchmarkFloat32-4 10000000 155 ns/op 24 B/op 2 allocs/op BenchmarkFloat64-4 10000000 177 ns/op 24 B/op 2 allocs/op BenchmarkTime-4 5000000 240 ns/op 72 B/op 4 allocs/op BenchmarkTimeDuration-4 50000000 26.2 ns/op 8 B/op 1 allocs/op BenchmarkBytes-4 10000000 149 ns/op 128 B/op 3 allocs/op BenchmarkStrings-4 10000000 223 ns/op 40 B/op 3 allocs/op BenchmarkInts-4 20000000 55.0 ns/op 16 B/op 2 allocs/op BenchmarkFloats-4 10000000 186 ns/op 32 B/op 3 allocs/op BenchmarkInterfaces-4 20000000 66.6 ns/op 24 B/op 2 allocs/op PASS ok command-line-arguments 35.356s
以上所述就是小编给大家介绍的《Golang类型转换模块 - gconv》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- JavaScript进阶系列-类型转换、隐式类型转换
- Android 多国语言转换 Excel 和 Excel 转换为 string
- [SSL证书转换(一)]关于JKS 转换成 CRT 和 KEY
- c++中几种常见的类型转换。int与string的转换,float与string的转换以及string和long类型之间的相互...
- Protocol Buffer使用转换工具将proto文件转换成Java文件流程及使用
- 开源 | Alita:一套把 React Native 代码转换成微信小程序代码的转换引擎工具
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Filter Bubble
Eli Pariser / Penguin Press / 2011-5-12 / GBP 16.45
In December 2009, Google began customizing its search results for each user. Instead of giving you the most broadly popular result, Google now tries to predict what you are most likely to click on. Ac......一起来看看 《The Filter Bubble》 这本书的介绍吧!