Copy one struct to another where structs have same members and different types
我有两个具有相同成员的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | type Common struct { Gender int From string To string } type Foo struct { Id string Name string Extra Common } type Bar struct { Id string Name string Extra Common } |
然后我有结构
使用转换来更改类型。以下代码使用转换将类型
1 2 | foo := Foo{Id:"123", Name:"Joe"} bar := Bar(foo) |
游乐场的例子
仅当基础类型相同(结构标记除外)时,转换才有效。
如果您想复制或克隆到其他结构,我建议使用deepcopier
它提供了很好的功能,例如跳过,自定义映射和强制。以下是来自github的示例:
安装:
1 | go get -u github.com/ulule/deepcopier |
例:
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | package main import ( "fmt" "github.com/ulule/deepcopier" ) // Model type User struct { // Basic string field Name string // Deepcopier supports https://golang.org/pkg/database/sql/driver/#Valuer Email sql.NullString } func (u *User) MethodThatTakesContext(ctx map[string]interface{}) string { // do whatever you want return"hello from this method" } // Resource type UserResource struct { //copy from field"Name" DisplayName string `deepcopier:"field:Name"` //this will be skipped in copy SkipMe string `deepcopier:"skip"` //this should call method named MethodThatTakesContext MethodThatTakesContext string `deepcopier:"context"` Email string `deepcopier:"force"` } func main() { user := &User{ Name:"gilles", Email: sql.NullString{ Valid: true, String:"[email protected]", }, } resource := &UserResource{} deepcopier.Copy(user).To(resource) //copied from User's Name field fmt.Println(resource.DisplayName)//output: gilles fmt.Println(resource.Email) //output: [email protected] fmt.Println(resource.MethodThatTakesContext) //output: hello from this method } |
另外,可以通过将源对象编码为JSON,然后将其解码回目标对象来实现。
https://github.com/jinzhu/copier(gorm的同一作者)也很不错,我嵌套了结构,我所做的就是:
效果很好
这是另一个可能的答案
输入Common struct {
性别诠释
从字符串
串
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | type Foo struct { Id string Name string Extra Common } type Bar struct { Id string Name string Extra Common } foo:=Foo{ Id:"123", Name:"damitha", Extra: struct { Gender int From string To string }{Gender:1 , From:"xx", To:"yy" }, } bar:=*(*Bar)(unsafe.Pointer(&foo)) fmt.Printf("%+v\ ",bar) |
如果您想复制或克隆到其他结构,我建议使用deepcopier
它提供了很好的功能,例如跳过,自定义映射和强制。
您可以按照以下方式实现嵌套的struct复制。
安装:
1 | go get -u github.com/ulule/deepcopier |
例:
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | package main import ( "fmt" "strconv" "github.com/ulule/deepcopier" ) //FieldStruct - Field Struct type FieldStruct struct { Name string `deepcopier:"field:TargetName"` Type string `deepcopier:"field:TargetType"` } //SourceStruct - Source Struct type SourceStruct struct { Name string `deepcopier:"field:TargetName"` Age int `deepcopier:"field:TargetAge"` StringArray []string `deepcopier:"field:TargetStringArray"` StringToInt string `deepcopier:"context"` Field FieldStruct Fields []FieldStruct } //TargetFieldStruct - Field Struct type TargetFieldStruct struct { TargetName string TargetType string } //TargetStruct - Target Struct type TargetStruct struct { TargetName string TargetAge int TargetStringArray []string TargetInt int TargetField TargetFieldStruct TargetFields []TargetFieldStruct } //write methods //TargetInt - StringToInt func (s *SourceStruct) TargetInt() int { i, _ := strconv.Atoi(s.StringToInt) return i } func main() { s := &SourceStruct{ Name: "Name", Age: 12, StringArray: []string{"1","2"}, StringToInt:"123", Field: FieldStruct{ Name:"Field", Type:"String", }, Fields: []FieldStruct{ FieldStruct{ Name:"Field1", Type:"String1", }, FieldStruct{ Name:"Field2", Type:"String2", }, }, } t := &TargetStruct{} //coping data into inner struct deepcopier.Copy(&t.TargetField).From(&s.Field) // copied array of Struct for i := range s.Fields { // init a struct t.TargetFields = append(t.TargetFields, TargetFieldStruct{}) // coping the data deepcopier.Copy(&t.TargetFields[i]).From(&s.Fields[i]) } //Top level copy deepcopier.Copy(t).From(s) fmt.Println(t) } |
输出:
&{名称12 [1 2] 123 {字段字符串} [{Field1 String1} {Field2 String2}]}