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 のコピーはリフレクションに依存しているため、いくつかのパフォーマンス損失があります。一般的に、この種の型変換ライブラリは 2 つのカテゴリに分かれます:1 つは copier のようなリフレクションベース、もう 1 つはコード生成ベースで、型変換コードを生成します。この方法はパフォーマンス損失を引き起こさず、同様のライブラリは jmattheis/goverter です。
インストール
sh
go get github.com/jinzhu/copier使用方法
このライブラリの使い方は非常にシンプルですが、非常に実用的です。2 つの関数のみを公開しています。1 つは copier.Copy です。
go
func Copy(toValue interface{}, fromValue interface{}) (err error)もう 1 つは 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("エラータイプ")
}
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:}]