Skip to content

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.

التثبيت

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:}]

نسخ خريطة

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:}]

Golang تم تحريره بواسطة www.golangdev.cn