Skip to content

copier

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

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

Copier ist eine Bibliothek für die Typkopie in Go, die hauptsächlich für die Konvertierung zwischen Strukturen verwendet wird. Der Autor ist derselbe wie bei GORM, und es hat folgende Eigenschaften:

  • Tiefenkopie
  • Kopieren von gleichnamigen Feldern
  • Kopieren von Slices
  • Kopieren von Maps
  • Kopieren von Methoden

Da die Kopie von Copier auf Reflexion basiert, gibt es gewisse Leistungsverluste. Im Allgemeinen werden solche Typkopie-Bibliotheken in zwei Kategorien unterteilt: eine basiert auf Reflexion, wie Copier, die andere basiert auf Codegenerierung, indem Typkonvertierungscode generiert wird. Diese Methode führt zu keinen Leistungsverlusten, ähnlich wie bei der Bibliothek jmattheis/goverter.

Installation

sh
 go get github.com/jinzhu/copier

Verwendung

Diese Bibliothek ist sehr einfach zu verwenden, aber äußerst praktisch. Sie stellt nur zwei Funktionen öffentlich zur Verfügung, eine ist copier.Copy.

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

Die andere ist copier.CopyWithOption, mit der das Kopierverhalten angepasst werden kann. Standardmäßig wird keine Tiefenkopie durchgeführt.

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

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

Im Folgenden wird ein Beispiel für die Konvertierung zwischen verschiedenen Strukturtypen gezeigt, wobei User und Student zwei völlig unterschiedliche Typen ohne Verbindung sind.

go
type User struct {
  Id   string
  Name string
  // Wird ignoriert, wenn als Zielstruktur verwendet
  Address string `copier:"-"`
}

type Student struct {
  // Feldname angeben
  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)
}

Ausgabe

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

Im Folgenden wird das Kopieren von Slices gezeigt

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

Ausgabe

[{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 kopieren

go
type User struct {
  Id   string
  Name string
  // Wird ignoriert, wenn als Zielstruktur verwendet
  Address string `copier:"-"`
}

type Student struct {
  // Feldname angeben
  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)
}

Ausgabe

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

Anpassung

Sie können auch benutzerdefinierte Konvertierungsmethoden definieren, indem Sie copier.TypeConverter übergeben:

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

Wie unten gezeigt:

go
type User struct {
  Id   string
  Name string
  // Wird ignoriert, wenn als Zielstruktur verwendet
  Address string `copier:"-"`
}

type Student struct {
  // Feldname angeben
  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)
}

Ausgabe

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