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 มีคุณสมบัติดังนี้
- การคัดลอกลึก
- คัดลอกฟิลด์ที่มีชื่อเดียวกัน
- คัดลอกสไลซ์
- คัดลอก map
- คัดลอกเมธอด
เนื่องจาก copier อาศัยการสะท้อน (reflection) ในการคัดลอก ดังนั้นประสิทธิภาพจะสูญเสียไปบ้าง โดยทั่วไปไลบรารีคัดลอกประเภทแบบนี้แบ่งเป็นสองประเภท ประเภทหนึ่งอาศัยการสะท้อน เช่น copier อีกประเภทหนึ่งอาศัยการสร้างโค้ด โดยสร้างโค้ดแปลงประเภท วิธีนี้ประสิทธิภาพไม่สูญเสีย ไลบรารีที่ใช้งานคล้ายกันคือ jmattheis/goverter
การติดตั้ง
go get github.com/jinzhu/copierการใช้งาน
ไลบรารีนี้ใช้งานง่ายมากแต่มีประโยชน์มาก เปิดเผยฟังก์ชันสองฟังก์ชันเท่านั้น หนึ่งคือ copier.Copy
func Copy(toValue interface{}, fromValue interface{}) (err error)อีกฟังก์ชันคือ copier.CopyWithOption ฟังก์ชันหลังสามารถกำหนดค่าการคัดลอกได้บ้าง ในกรณีเริ่มต้นจะไม่ทำการคัดลอกลึก
type Option struct {
IgnoreEmpty bool
CaseSensitive bool
DeepCopy bool
FieldNameMapping []FieldNameMapping
}
func CopyWithOption(toValue interface{}, fromValue interface{}, opt Option) (err error)ด้านล่างนี้สาธิตตัวอย่างการแปลงโครงสร้างประเภทต่างกัน User และ Student เป็นโครงสร้างสองประเภทที่ต่างกันโดยสิ้นเชิง ไม่มีความเกี่ยวข้องใดๆ
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:}ด้านล่างดูการคัดลอกสไลซ์
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:}]คัดลอก map
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
type TypeConverter struct {
SrcType interface{}
DstType interface{}
Fn func(src interface{}) (dst interface{}, err error)
}ดังต่อไปนี้
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("error type")
}
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:}]