Skip to content

copier

Repositori Open Source: jinzhu/copier: Copier for golang, copy value from struct to struct and more (github.com)

Dokumentasi: jinzhu/copier: Copier for golang, copy value from struct to struct and more (github.com)

Copier adalah library untuk menyalin tipe dalam Go sering digunakan untuk konversi antar struktur penulisnya sama dengan gorm memiliki fitur berikut

  • Deep copy
  • Menyalin field dengan nama yang sama
  • Menyalin slice
  • Menyalin map
  • Menyalin method

Karena penyalinan copier bergantung pada refleksi akan ada kerugian performa. Umumnya library jenis penyalinan tipe seperti ini terbagi menjadi dua kategori satu berdasarkan refleksi seperti copier ini yang lain berdasarkan generasi kode dengan menghasilkan kode konversi tipe metode ini tidak menyebabkan kerugian performa library serupa adalah jmattheis/goverter.

Instalasi

sh
go get github.com/jinzhu/copier

Penggunaan

Library ini sangat sederhana untuk digunakan namun sangat praktis. Hanya mengekspos dua fungsi satu adalah copier.Copy.

go
func Copy(toValue interface{}, fromValue interface{}) (err error)

Yang lain adalah copier.CopyWithOption yang terakhir dapat melakukan beberapa konfigurasi kustom pada perilaku penyalinan secara default tidak akan melakukan deep copy.

go
type Option struct {
  IgnoreEmpty   bool
  CaseSensitive bool
  DeepCopy      bool
  FieldNameMapping []FieldNameMapping
}

func CopyWithOption(toValue interface{}, fromValue interface{}, opt Option) (err error)

Berikut adalah contoh konversi struktur tipe berbeda User dan Student adalah dua tipe yang sama sekali berbeda tidak ada asosiasi apapun.

go
type User struct {
  Id   string
  Name string
  // Abaikan field ini saat sebagai struktur target
  Address string `copier:"-"`
}

type Student struct {
  // Tentukan nama field
  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)
}

Output

{StudentId:123 StudentName:jack Address:usa School:MIT Class:AI}
{Id:123 Name:jack Address:}

Berikut penyalinan slice

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)
}

Output

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

Menyalin map

go
type User struct {
  Id   string
  Name string
  // Abaikan field ini saat sebagai struktur target
  Address string `copier:"-"`
}

type Student struct {
  // Tentukan nama field
  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)
}

Output

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

Kustomisasi

Juga dapat menyesuaikan metode konversi cukup dengan mengirimkan copier.TypeConverter

go
type TypeConverter struct {
  SrcType interface{}
  DstType interface{}
  Fn      func(src interface{}) (dst interface{}, err error)
}

Seperti berikut

go
type User struct {
  Id   string
  Name string
  // Abaikan field ini saat sebagai struktur target
  Address string `copier:"-"`
}

type Student struct {
  // Tentukan nama field
  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)
}

Output

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 by www.golangdev.cn edit