Skip to content

copier

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

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

copier Go'da tip kopyalama için bir kütüphanedir. Çoğunlukla struct'tan struct'a dönüşüm için kullanılır. gorm ile aynı yazar tarafından yazılmıştır ve aşağıdaki özelliklere sahiptir:

  • Derin kopyalama
  • Aynı isimli alanları kopyalama
  • Slice'ları kopyalama
  • Map'leri kopyalama
  • Metodları kopyalama

copier'ın kopyalaması yansıma (reflection) kullandığından bazı performans kayıpları olacaktır. Genel olarak bu tür tip dönüşüm kütüphaneleri iki kategoriye ayrılır: biri copier gibi yansıma tabanlıdır, diğeri kod üretimi tabanlıdır ve tip dönüşüm kodu üretir. Bu yöntem performans kaybına neden olmaz. Benzer bir kütüphane jmattheis/goverter'dır.

Kurulum

sh
go get github.com/jinzhu/copier

Kullanım

Bu kütüphane kullanımı çok basit ancak oldukça pratiktir. Yalnızca iki fonksiyonu kullanıma sunar. Biri copier.Copy:

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

Diğeri copier.CopyWithOption kopyalama davranışı için bazı özel yapılandırmalara izin verir. Varsayılan olarak derin kopyalama yapılmaz:

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

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

Farklı struct türleri arasında dönüşüm örneği. User ve Student struct'ları hiçbir ilişkisi olmayan tamamen farklı türlerdir:

go
type User struct {
  Id   string
  Name string
  // Hedef struct olarak kullanıldığında bu alanı yoksay
  Address string `copier:"-"`
}

type Student struct {
  // Alan adını belirt
  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)
}

Çıktı:

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

Slice kopyalama:

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

Çıktı:

[{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 kopyalama:

go
type User struct {
  Id   string
  Name string
  // Hedef struct olarak kullanıldığında bu alanı yoksay
  Address string `copier:"-"`
}

type Student struct {
  // Alan adını belirt
  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)
}

Çıktı:

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

Özelleştirme

copier.TypeConverter geçirerek dönüşüm metodunu özelleştirebilirsiniz:

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

Aşağıdaki gibi:

go
type User struct {
  Id   string
  Name string
  // Hedef struct olarak kullanıldığında bu alanı yoksay
  Address string `copier:"-"`
}

type Student struct {
  // Alan adını belirt
  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("hata türü")
          }
          return User{
            Id: s.StudentId,
          }, nil
        },
      },
    },
    FieldNameMapping: nil,
  }); err != nil {
    panic(err)
  }
  fmt.Printf("%+v\n", src)
  fmt.Printf("%+v\n", dest)
}

Çıktı:

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