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، وتتميز بالخصائص التالية:
- نسخ عميق
- نسخ الحقول التي تحمل نفس الاسم
- نسخ الشرائح
- نسخ الخرائط
- نسخ الطرق
بما أن نسخ copier يعتمد على الانعكاس، فسيكون هناك فقدان في الأداء. عمومًا تنقسم مكتبات نسخ الأنواع إلى فئتين: واحدة تعتمد على الانعكاس، مثل copier، والأخرى تعتمد على توليد الكود، من خلال توليد كود تحويل الأنواع، وهذه الطريقة لا تسبب فقدان في الأداء، والمكتبات المشابهة في التنفيذ مثل jmattheis/goverter.
التثبيت
go get github.com/jinzhu/copierالاستخدام
هذه المكتبة سهلة الاستخدام للغاية، لكنها عملية جدًا. إنها تكشف دالتين فقط، واحدة هي copier.Copy.
func Copy(toValue interface{}, fromValue interface{}) (err error)والأخرى هي copier.CopyWithOption، التي تسمح بتخصيص سلوك النسخ، وبشكل افتراضي لا يتم إجراء نسخ عميق.
type Option struct {
IgnoreEmpty bool
CaseSensitive bool
DeepCopy bool
FieldNameMapping []FieldNameMapping
}
func CopyWithOption(toValue interface{}, fromValue interface{}, opt Option) (err error)فيما يلي مثال على التحويل بين بنى من أنواع مختلفة، حيث البنيتان User و Student نوعان مختلفان تمامًا بدون أي ارتباط.
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:}فيما يلي نسخ شريحة
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:}]نسخ خريطة
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
type TypeConverter struct {
SrcType interface{}
DstType interface{}
Fn func(src interface{}) (dst interface{}, err error)
}كما في المثال التالي
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:}]