上一篇文章介紹了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】,共同窗習,一塊兒進步~