Подтвердить что ты не робот

Назначить структуру другой структурой

У меня есть структура 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 после регистрации.

Итак, у меня есть две переменные: req и u - по одному для каждой структуры. Можно ли назначить структуру req в структуру u, чтобы все общие поля существовали в структуре u?

4b9b3361

Ответ 1

Используя простой assignment, вы не можете, потому что, хотя поля User являются подмножеством RegistrationRequest, они полностью 2 разных типа, а Assignability правила не применяются.

Вы можете написать функцию, которая использует отражение (reflect package) и скопирует все поля из req в u, но это просто уродливо (и неэффективно).

Лучше всего было бы реорганизовать ваши типы, а 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 := "[email protected]"
    req.Email = &s

    s2 := "testuser"
    req.Username = &s2

    u := User{}
    u = req.User
    fmt.Println(*u.Username, *u.Email)
}

Выход: (попробуйте на Go Playground)

testuser [email protected]

Также обратите внимание, что поскольку ваши структуры содержат указатели, при копировании struct значения указателя будут скопированы и не указаны. Я не уверен, почему вам нужны указатели здесь, было бы лучше всего объявить все поля не указателями.

Также обратите внимание, что внедрение не является требованием, оно просто делает ваши типы и их использование более плавными. User также может быть "обычным" полем RequistrationRequest, например:

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

Ответ 2

Вы можете использовать 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 = "[email protected]"
    *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 [email protected] johndoe 1234
 RegistrationRequest : John Doe [email protected] johndoe 1234