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