使用另一个结构分配struct

时间:2015-08-13 07:03:25

标签: struct go

我有一个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

所以我有两个变量:requ - 每个结构一个。是否可以将req结构分配到u结构中,以便所有公共字段都存在于u结构中?

2 个答案:

答案 0 :(得分:19)

使用简单的assignment是不可能的,因为即使User的字段是RegistrationRequest的子集,它们也完全是2种不同的类型,Assignability规则不适用。

您可以编写一个使用反射(reflect包)的函数,并将所有字段从req复制到u,但这只是丑陋(且效率低下)。< / p>

最好是重构您的类型,而RegistrationRequest可以embed 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也可能是一个普通的&#34; RequistrationRequest的字段,例如:

type RegistrationRequest struct {
    Usr User // This is just an ordinary field, not embedding
    Email2 *string
}

答案 1 :(得分:1)

您可以使用&#34; github.com/jinzhu/copier&#34; package to包含包含相同字段名称的结构。这个包使用反射来做到这一点。

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