copier
開源倉庫:jinzhu/copier: Copier for golang, copy value from struct to struct and more (github.com)
文檔地址:jinzhu/copier: Copier for golang, copy value from struct to struct and more (github.com)
copier 是一個用於在 go 中進行類型復制的庫,多用於結構體之間的轉換。作者和 gorm 是同一個,它具有以下特點
- 深拷貝
- 復制同名的字段
- 復制切片
- 復制 map
- 復制方法
由於 copier 的復制依賴於反射,所以性能上會有一定的損失。一般這種類型復制的庫分成兩類,一類基於反射,也是就 copier 這種,另一類是基於代碼生成,通過生成類型轉換的代碼,這種方法性能不會造成損失,類似實現的庫有jmattheis/goverter。
安裝
sh
go get github.com/jinzhu/copier使用
這個庫使用起來非常簡單,但卻非常的實用。它只對外暴露兩個函數,一個是copier.Copy。
go
func Copy(toValue interface{}, fromValue interface{}) (err error)另一個是copier.CopyWithOption,後者可以對復制行為進行一些自定義的配置,在默認情況下不會進行深拷貝。
go
type Option struct {
IgnoreEmpty bool
CaseSensitive bool
DeepCopy bool
FieldNameMapping []FieldNameMapping
}
func CopyWithOption(toValue interface{}, fromValue interface{}, opt Option) (err error)下面演示一個不同類型結構體轉換的例子,其中的User和Student結構體是兩個完全不同的類型,沒有任何的關聯。
go
type User struct {
Id string
Name string
// 當作為目標結構體時,忽略該字段
Address string `copier:"-"`
}
type Student struct {
// 指定字段名
StudentId string `copier:"Id"`
StudentName string `copier:"Name"`
Address string
School string
Class string
}
func main() {
student := Student{
StudentId: "123",
StudentName: "jack",
Address: "usa",
School: "MIT",
Class: "AI",
}
user := User{}
if err := copier.Copy(&user, &student); err != nil {
panic(err)
}
fmt.Printf("%+v\n", student)
fmt.Printf("%+v\n", user)
}輸出
{StudentId:123 StudentName:jack Address:usa School:MIT Class:AI}
{Id:123 Name:jack Address:}下面看復制切片
go
func main() {
student := []Student{
{
StudentId: "123",
StudentName: "jack",
Address: "usa",
School: "MIT",
Class: "AI",
},
{
StudentId: "123",
StudentName: "jack",
Address: "usa",
School: "MIT",
Class: "AI",
},
}
var user []User
if err := copier.Copy(&user, &student); err != nil {
panic(err)
}
fmt.Printf("%+v\n", student)
fmt.Printf("%+v\n", user)
}輸出
[{StudentId:123 StudentName:jack Address:usa School:MIT Class:AI} {StudentId:123 StudentName:jack Address:usa School:MIT Class:AI}]
[{Id:123 Name:jack Address:} {Id:123 Name:jack Address:}]復制 map
go
type User struct {
Id string
Name string
// 當作為目標結構體時,忽略該字段
Address string `copier:"-"`
}
type Student struct {
// 指定字段名
StudentId string `copier:"Id"`
StudentName string `copier:"Name"`
Address string
School string
Class string
}
func main() {
student := Student{
StudentId: "123",
StudentName: "jack",
Address: "usa",
School: "MIT",
Class: "AI",
}
src := make(map[string]Student)
src["a"] = student
src["b"] = student
dest := make(map[string]User)
if err := copier.Copy(&dest, &src); err != nil {
panic(err)
}
fmt.Printf("%+v\n", src)
fmt.Printf("%+v\n", dest)
}輸出
map[a:{StudentId:123 StudentName:jack Address:usa School:MIT Class:AI} b:{StudentId:123 StudentName:jack Address:usa School:MIT Class:AI}]
map[a:{Id:123 Name:jack Address:} b:{Id:123 Name:jack Address:}]自定義
還可以自定義轉換方法,只需要傳入copier.TypeConverter即可
go
type TypeConverter struct {
SrcType interface{}
DstType interface{}
Fn func(src interface{}) (dst interface{}, err error)
}如下所示
go
type User struct {
Id string
Name string
// 當作為目標結構體時,忽略該字段
Address string `copier:"-"`
}
type Student struct {
// 指定字段名
StudentId string `copier:"Id"`
StudentName string `copier:"Name"`
Address string
School string
Class string
}
func main() {
student := Student{
StudentId: "123",
StudentName: "jack",
Address: "usa",
School: "MIT",
Class: "AI",
}
src := make(map[string]Student)
src["a"] = student
src["b"] = student
dest := make(map[string]User)
if err := copier.CopyWithOption(&dest, &src, copier.Option{
IgnoreEmpty: false,
CaseSensitive: false,
DeepCopy: false,
Converters: []copier.TypeConverter{
{
SrcType: Student{},
DstType: User{},
Fn: func(src interface{}) (dst interface{}, err error) {
s, ok := src.(Student)
if !ok {
return User{}, errors.New("error type")
}
return User{
Id: s.StudentId,
}, nil
},
},
},
FieldNameMapping: nil,
}); err != nil {
panic(err)
}
fmt.Printf("%+v\n", src)
fmt.Printf("%+v\n", dest)
}輸出
map[a:{StudentId:123 StudentName:jack Address:usa School:MIT Class:AI} b:{StudentId:123 StudentName:jack Address:usa School:MIT Class:AI}]
map[a:{Id:123 Name: Address:} b:{Id:123 Name: Address:}]