Скопируйте одну структуру в другую, где структуры имеют одинаковых членов и разные типы
У меня есть две struct
имеющие одинаковые члены, я хочу скопировать одну структуру в другую, см. Псевдокод ниже:
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
}
Тогда у меня есть foo
структуры Foo
и bar
структуры Bar
Есть ли способ скопировать bar
из foo
?
Ответы
Ответ 1
Используйте конверсию. В следующем коде используется преобразование для копирования значения типа Foo
в значение типа Bar
:
foo := Foo{Id: "123", Name: "Joe"}
bar := Bar(foo)
Пример детской площадки
преобразование работает только тогда, когда базовые типы идентичны, за исключением тегов структуры.
Ответ 2
Если вы хотите скопировать или клонировать другую структуру, я бы предложил использовать deepcopier
Это обеспечивает хорошие функции, такие как пропуск, пользовательское сопоставление и форсирование. ниже приведен пример из github:
Установка:
go get -u github.com/ulule/deepcopier
Пример:
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 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, а затем декодирования его обратно в целевой объект.
Ответ 3
https://github.com/jinzhu/copier (тот же автор gorm) также довольно хороший, у меня есть вложенные структуры, и все, что я делаю, это:
copier.Copy(&employees, &user)
работает отлично
Ответ 4
Если вы хотите скопировать или клонировать другую структуру, я бы предложил использовать deepcopier
Он предоставляет хорошие функции, такие как пропуск, пользовательское сопоставление и форсирование.
Вы можете добиться вложенного копирования структуры следующим образом.
Установить:
go get -u github.com/ulule/deepcopier
Пример:
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 [12] 123 {Строка поля} [{Строка1 Строка1} {Строка2 Строка2}]}