copier
Dépôt open source : jinzhu/copier: Copier for golang, copy value from struct to struct and more (github.com)
Adresse de la documentation : jinzhu/copier: Copier for golang, copy value from struct to struct and more (github.com)
copier est une bibliothèque pour la copie de types en Go, principalement utilisée pour la conversion entre structures. L'auteur est le même que gorm, elle possède les caractéristiques suivantes :
- Copie profonde
- Copie les champs de même nom
- Copie les slices
- Copie les maps
- Copie les méthodes
Comme la copie de copier repose sur la réflexion, il y a une certaine perte de performance. Généralement, ce type de bibliothèque de copie se divise en deux catégories : une basée sur la réflexion, comme copier, et l'autre basée sur la génération de code, qui génère du code de conversion de types. Cette méthode n'entraîne pas de perte de performance. Une bibliothèque similaire est jmattheis/goverter.
Installation
go get github.com/jinzhu/copierUtilisation
Cette bibliothèque est très simple à utiliser mais très pratique. Elle expose uniquement deux fonctions. L'une est copier.Copy.
func Copy(toValue interface{}, fromValue interface{}) (err error)L'autre est copier.CopyWithOption, qui permet de personnaliser certains comportements de copie. Par défaut, elle n'effectue pas de copie profonde.
type Option struct {
IgnoreEmpty bool
CaseSensitive bool
DeepCopy bool
FieldNameMapping []FieldNameMapping
}
func CopyWithOption(toValue interface{}, fromValue interface{}, opt Option) (err error)Voici un exemple de conversion entre structures de types différents. Les structures User et Student sont deux types complètement différents, sans aucune relation.
type User struct {
Id string
Name string
// Lorsque utilisé comme structure cible, ignore ce champ
Address string `copier:"-"`
}
type Student struct {
// Spécifie le nom du champ
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)
}Sortie
{StudentId:123 StudentName:jack Address:usa School:MIT Class:AI}
{Id:123 Name:jack Address:}Voyons maintenant la copie de slices
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)
}Sortie
[{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:}]Copie de map
type User struct {
Id string
Name string
// Lorsque utilisé comme structure cible, ignore ce champ
Address string `copier:"-"`
}
type Student struct {
// Spécifie le nom du champ
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)
}Sortie
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:}]Personnalisation
Il est également possible de personnaliser les méthodes de conversion en passant simplement copier.TypeConverter
type TypeConverter struct {
SrcType interface{}
DstType interface{}
Fn func(src interface{}) (dst interface{}, err error)
}Comme ci-dessous
type User struct {
Id string
Name string
// Lorsque utilisé comme structure cible, ignore ce champ
Address string `copier:"-"`
}
type Student struct {
// Spécifie le nom du champ
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)
}Sortie
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:}]