繁体   English   中英

用另一个结构分配结构

[英]Assign struct with another struct

我有一个 RegistrationRequest 结构:

type RegistrationRequest struct {
    Email    *string
    Email2   *string        
    Username *string
    Password *string
    Name     string
}

其中Email2是再次输入的电子邮件值,以验证用户输入的内容是否正确。

我也有一个用户结构:

type User struct {
    Email    *string
    Username *string
    Password *string
    Name     string           
}

当然, Email2不需要在注册后存储。

所以我有两个变量: requ - 每个结构一个。 是否可以将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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM