上一篇文章介绍了mergo
库的使用,mergo
是用来给结构体或map
赋值的。mergo
有一个明显的不足——它只能处理相同类型的结构!若是类型不一样,即便字段名和类型彻底相同,mergo
也无能为力。今天咱们要介绍的copier
库就能处理不一样类型之间的赋值。除此以外,copier
还能:git
感谢@thinkgos推荐。github
顺带一提,做者是国人jinzhu大佬,若是你想找一个 Go 语言的 ORM 库,gorm你值得拥有!golang
先安装:微信
$ go get github.com/jinzhu/copier
后使用:app
package main import ( "fmt" "github.com/jinzhu/copier" ) type User struct { Name string Age int } type Employee struct { Name string Age int Role string } func main() { user := User{Name: "dj", Age: 18} employee := Employee{} copier.Copy(&employee, &user) fmt.Printf("%#v\n", employee) }
很好理解,就是将user
对象中的字段赋值到employee
的同名字段中。若是目标对象中没有同名的字段,则该字段被忽略。函数
目标对象中的一些字段,源对象中没有,可是源对象有同名的方法。这时Copy
会调用这个方法,将返回值赋值给目标对象中的字段:学习
type User struct { Name string Age int } func (u *User) DoubleAge() int { return 2 * u.Age } type Employee struct { Name string DoubleAge int Role string } func main() { user := User{Name: "dj", Age: 18} employee := Employee{} copier.Copy(&employee, &user) fmt.Printf("%#v\n", employee) }
咱们给User
添加一个DoubleAge
方法。Employee
结构有字段DoubleAge
,User
中没有,可是User
有一个同名的方法,这时Copy
调用user
的DoubleAge
方法为employee
的DoubleAge
赋值,获得 36。spa
有时候源对象中的某个字段没有出如今目标对象中,可是目标对象有一个同名的方法,方法接受一个同类型的参数,这时Copy
会以源对象的这个字段做为参数调用目标对象的该方法:code
type User struct { Name string Age int Role string } type Employee struct { Name string Age int SuperRole string } func (e *Employee) Role(role string) { e.SuperRole = "Super" + role } func main() { user := User{Name: "dj", Age: 18, Role: "Admin"} employee := Employee{} copier.Copy(&employee, &user) fmt.Printf("%#v\n", employee) }
咱们给Employee
添加了一个Role
方法,User
的字段Role
没有出如今Employee
中,可是Employee
有一个同名方法。Copy
函数内部会以user
对象的Role
字段为参数调用employee
的Role
方法。最终,咱们的employee
对象的SuperRole
值变为SuperAdmin
。实际上,这个方法中能够执行任何操做,不必定是赋值。orm
使用一个切片来为另外一个切片赋值。若是类型相同,那好办,直接append
就行。若是类型不一样呢?copier
就派上大用场了:
type User struct { Name string Age int } type Employee struct { Name string Age int Role string } func main() { users := []User{ {Name: "dj", Age: 18}, {Name: "dj2", Age: 18}, } employees := []Employee{} copier.Copy(&employees, &users) fmt.Printf("%#v\n", employees) }
这个实际上就是将源切片中每一个元素分别赋值到目标切片中。
这个不难,实际上就是根据源对象生成一个和目标切片类型相符合的对象,而后append
到目标切片中:
type User struct { Name string Age int } type Employee struct { Name string Age int Role string } func main() { user := User{Name: "dj", Age: 18} employees := []Employee{} copier.Copy(&employees, &user) fmt.Printf("%#v\n", employees) }
上面代码中,Copy
先经过user
生成一个Employee
对象,而后append
到切片employees
中。
最后将全部的特性汇总在一个例子中,其实就是Copier
的 GitHub 仓库首页的例子:
type User struct { Name string Age int Role string } func (u *User) DoubleAge() int { return u.Age * 2 } type Employee struct { Name string Age int SuperRole string } func (e *Employee) Role(role string) { e.SuperRole = "Super" + role } func main() { var ( user = User{Name: "dj", Age: 18} users = []User{ {Name: "dj", Age: 18, Role: "Admin"}, {Name: "dj2", Age: 18, Role: "Dev"}, } employee = Employee{} employees = []Employee{} ) copier.Copy(&employee, &user) fmt.Printf("%#v\n", employee) copier.Copy(&employees, &user) fmt.Printf("%#v\n", employees) // employees = []Employee{} copier.Copy(&employees, &users) fmt.Printf("%#v\n", employees) }
上面例子中,我故意把employees = []Employee{}
这一行注释掉,最后输出的employees
是 3 个元素,能更清楚的看出切片到切片是append
的,目标切片原来的元素仍是保留的。
copier
库的代码量很小,用了不到 200 行的代码就实现了如此实用的一个功能,很是值得一看!
你们若是发现好玩、好用的 Go 语言库,欢迎到 Go 每日一库 GitHub 上提交 issue😄
欢迎关注个人微信公众号【GoUpUp】,共同窗习,一块儿进步~