前言
最近在重构公司项目的model
层,发现在数据库model
向返回ack model
之间的结构体转换时,因为model
字段多,则存在大量的直接赋值,不美观也不优雅,例如
| func (person *Person) MapTo() model.Student { var student model.Student now := time.Now() student.ID=person.ID student.Name=persobn.Name student.Age=persobn.Age student.Phone=persobn.Phone student.Address=persobn.Address student.Gender=persobn.Gender student.ParentPhone=persobn.ParentPhone student.Mother=persobn.Mother student.Father=persobn.Father student.Socre=100 return studnet }
|
而使用Go的copier库可以完成不同类型结构体相同字段的赋值,并且还可以完成不同字段的赋值,下面将进行简单的演示
安装
1
| go get github.com/jinzhu/copier
|
使用
字段名相同,类型相同
对于不同类型的结构体,如果字段名相同且字段类型相同,那么copier
就会对该字段直接赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| type Person struct { ID int Name string Age int Address string }
type Student struct { ID int Name string Age int Address string }
func main() { person := Person{ ID: 1, Name: "snow", Age: 22, Address: "China", } var student Student copier.Copy(&student, &person) fmt.Println(student) }
|
字段名相同,类型不同
对于这种情况copie
r是不会赋值的,则需要自己手动配置 (所以在model 和 ack间尽量不要设置字段名相同而类型不同)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| type Person struct { ID int Name string Age int Parent []string }
type Student struct { ID int Name string Age int Parent string }
func main() { person := Person{ ID: 1, Name: "snow", Age: 22, Parent: []string{"mother", "father"}, } var student Student copier.Copy(&student, &person) student.Parent=strings.Join(person.Parent,",") }
|
目标对象中出现不同字段名,但与源对象字段相关
有时候源对象某个字段没有出现在目标对象中,但是目标对象可以使用一个相同字段名的方法,方法接收相同类型的参数,这样在copier
Copy
时会以源对象的这个字段作为参数调用目标对象的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| type Person struct { ID int Name string Age int Nation string }
type Student struct { ID int Name string Age int Address string }
func (student *Student) Nation(nat string) { student.Address=nat+"BeiJin" }
func main() { person := Person{ ID: 1, Name: "snow", Age: 22, Nation: "China", } var student Student copier.Copy(&student, &person) fmt.Println(student) }
|
目标对象中出现不同字段名,但与源对象字段无关
对于这种情况就和字段名相同类型不同的方法一样,需要对这个字段单独处理
不同类型切片的赋值
1 2 3 4 5 6 7 8 9 10
| func main() { persons := []Person{ {ID: 1, Name: "snow",Age: 22}, {ID: 2, Name: "ice",Age: 18}, } var students []Student copier.Copy(&students, &persons) fmt.Println(students) }
|
结构体复制到切片
根据源对象生成一个和目标切片类型相符合的对象,然后append
到目标切片
1 2 3 4 5 6 7 8 9 10 11
| func main() { person := Person{ ID: 1, Name: "snow", Age: 22, } var students []Student copier.Copy(&students, &person) fmt.Println(students) }
|
总结
copier库
copier
还有很多玩法,本文章值列举了自己在改造时使用过的方法,具体信息可以看官方源码和文档