我有一个RegistrationRequest结构体:
type RegistrationRequest struct {
Email *string
Email2 *string
Username *string
Password *string
Name string
}
其中Email2
为再次输入的电子邮件值,用于验证用户输入的内容是否正确。
我还有一个User结构体:
type User struct {
Email *string
Username *string
Password *string
Name string
}
当然,没有必要在注册后存储Email2
。
所以我有两个变量:req
和u
-每个结构一个。是否有可能将req
结构体分配给u
结构体,以便所有公共字段都存在于u
结构体中?
使用简单赋值你不能,因为即使User
的字段是RegistrationRequest
的子集,它们是完全不同的两种类型,并且可赋值规则不适用。
你可以写一个函数,使用反射(reflect
包),并将所有的字段从req
复制到u
,但这只是丑陋(和低效)。
最好是重构你的类型,RegistrationRequest
可以嵌入User
。
如果你有一个类型为RegistrationRequest
的值,这意味着你已经有了User
的值:
type User struct {
Email *string
Username *string
Password *string
Name string
}
type RegistrationRequest struct {
User // Embedding User type
Email2 *string
}
func main() {
req := RegistrationRequest{}
s := "as@as.com"
req.Email = &s
s2 := "testuser"
req.Username = &s2
u := User{}
u = req.User
fmt.Println(*u.Username, *u.Email)
}
输出:(在Go Playground上试试)
testuser as@as.com
还请注意,因为你的结构体包含指针,当复制struct
时,指针值将被复制,而不是指向值。我不确定为什么这里需要指针,最好将所有字段声明为非指针。
还需要注意的是,嵌入并不是必需的,它只是使你的类型和它们的使用更顺畅。User
也可以是RequistrationRequest
的一个"普通"字段,例如:
type RegistrationRequest struct {
Usr User // This is just an ordinary field, not embedding
Email2 *string
}
您可以使用"github.com/jinzhu/copier"包在包含相同字段名的结构体之间进行复制。这个包使用反射来做这个。
package main
import (
"fmt"
"github.com/jinzhu/copier"
)
type RegistrationRequest struct {
Email *string
Email2 *string
Username *string
Password *string
Name string
}
type User struct {
Email *string
Username *string
Password *string
Name string
}
func main() {
user := new(User)
req := new(RegistrationRequest)
user.Email, user.Password, user.Username = new(string), new(string), new(string)
user.Name = "John Doe"
*user.Email = "a@b.com"
*user.Password = "1234"
*user.Username = "johndoe"
fmt.Println("User :",user.Name, *user.Email, *user.Username, *user.Password)
copier.Copy(req, user)
fmt.Println("RegistrationRequest :",req.Name, *req.Email, *req.Username, *req.Password)
}
输出 User : John Doe a@b.com johndoe 1234
RegistrationRequest : John Doe a@b.com johndoe 1234
func ObjectAssign(target interface{}, object interface{}) {
// object atributes values in target atributes values
// using pattern matching (https://golang.org/pkg/reflect/#Value.FieldByName)
// https://stackoverflow.com/questions/35590190/how-to-use-the-spread-operator-in-golang
t := reflect.ValueOf(target).Elem()
o := reflect.ValueOf(object).Elem()
for i := 0; i < o.NumField(); i++ {
for j := 0; j < t.NumField(); j++ {
if t.Field(j).Name() == o.Field(i).Name() {
t.Field(j).Set(o.Field(i))
}
}
}
}
如果第二个结构是第一个结构的克隆,具有更少的字段,您可以通过json转换结构。
type user1 struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
UserName string `json:"user_name"`
}
type user2 struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
…
u1Json, _ := json.Marshal(u1)
_ = json.Unmarshal(u1Json,&u2)