2015-08-13 41 views
11

ho una struct RegistrationRequest:Assegnare struct con un altro struct

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

Dove Email2 è il valore-mail entrò di nuovo per verificare che ciò che l'utente inserito è corretto.

Ho anche una struct User:

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

Naturalmente, non v'è alcuna necessità di memorizzare Email2 al di là di registrazione.

Quindi ho due variabili: req e u - una per ogni struttura. È possibile assegnare la struttura req alla struttura u in modo che tutti i campi comuni esistano nella struttura u?

+0

vuoi dire struct incorporamento? – alexsmn

risposta

14

utilizzando semplici assignment non è possibile perché, anche se i campi di User sono un sottoinsieme di RegistrationRequest, sono completamente 2 tipi diversi, e Assignability regole non si applicano.

È possibile scrivere una funzione che utilizza la riflessione (pacchetto reflect) e copierà tutti i campi da req a u, ma è solo brutto (e inefficiente).

Il migliore sarebbe il refactoring dei tipi e RegistrationRequestembedUser.

In questo modo, se si dispone di un valore di tipo RegistrationRequest che significa che già hanno anche un valore di 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) 
} 

uscita: (provate sul Go Playground)

testuser [email protected] 

Inoltre si prega di si noti che poiché le strutture contengono puntatori, quando si copia un struct, i valori del puntatore verranno copiati e non i valori puntati. Non sono sicuro del motivo per cui hai bisogno di indicazioni qui, sarebbe meglio dichiarare tutti i campi come non puntatori.

Inoltre, l'incorporamento non è un requisito, ma rende i tipi e il loro utilizzo più semplici. User potrebbe benissimo essere un campo di "ordinario" di RequistrationRequest, ad es .:

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

NICE approccio - questo dovrebbe funzionare per me. Andando a provarlo ora. – tommyd456

+0

Domanda laterale: il campo "Utente" in "RegistrationRequest" - "assume" il tipo è "Utente" come nulla è definito. – tommyd456

+0

@ tommyd456 Si prega di leggere cosa è [embedding] (http://golang.org/ref/spec#Struct_types). Quando si incorpora, viene fornito solo _type_, ma non il _name_. Quindi 'User' _is_ il tipo. E i campi di 'User' sono _promoted_ nella struttura embedder.Ma puoi fare riferimento al valore incorporato usando il nome del tipo. – icza

0

È possibile utilizzare "github.com/jinzhu/copier" pacchetto copiare tra le strutture che contengono lo stesso nome del campo. Questo pacchetto utilizza la riflessione per farlo.

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) 
} 

uscita

User : John Doe [email protected] johndoe 1234 
RegistrationRequest : John Doe [email protected] johndoe 1234