2015-08-13 20 views
11

Mam struct RegistrationRequest:Przypisywanie struct z innej struktury

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

Gdzie Email2 jest wartością email wszedł ponownie, aby sprawdzić, co użytkownik wpisane jest poprawna.

Mam też struct użytkownika:

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

Oczywiście, nie ma potrzeby przechowywać Email2 poza rejestracją.

Mam dwie zmienne: req i u - po jednej dla każdej struktury. Czy jest możliwe przypisanie struktury req do struktury u, aby wszystkie wspólne pola istniały w strukturze u?

+0

znaczy struct osadzanie? – alexsmn

Odpowiedz

14

Korzystanie prosty assignment nie można, bo chociaż pola User są podzbiorem RegistrationRequest, są zupełnie 2 różne typy i Assignability zasady nie mają zastosowania.

Można napisać funkcję, która używa odbicia (pakiet reflect) i skopiowałaby wszystkie pola od req do u, ale jest to po prostu brzydkie (i nieefektywne).

Najlepiej byłoby zmienić swoje typy, a RegistrationRequest może embedUser.

Robi więc jeśli mają wartość typu RegistrationRequest Oznacza to, że już też mieć wartość 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) 
} 

wyjściowy: (spróbuj na Go Playground)

testuser [email protected] 

także proszę Zwróć uwagę, że skoro Twoje konstrukcje zawierają wskaźniki, podczas kopiowania wartości struct, wartości wskaźników będą kopiowane, a nie wskazywane wartości. Nie jestem pewien, dlaczego potrzebujesz wskazówek tutaj, najlepiej byłoby po prostu zadeklarować, że wszystkie pola nie są wskaźnikami.

Należy również pamiętać, że osadzanie nie jest tak naprawdę wymogiem, tylko sprawia, że ​​twoje typy i ich wykorzystanie jest bardziej płynne. User może równie dobrze być „zwykłe” pole RequistrationRequest, np .:

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

NIce approach - to powinno działać dla mnie. Teraz spróbuję. – tommyd456

+0

Pytanie boczne: W polu "Użytkownik" w "RegistrationRequest" - czy "przyjmuje" typ "Użytkownik", ponieważ nic nie jest zdefiniowane. – tommyd456

+0

@ tommyd456 Przeczytaj, co [embedding] (http://golang.org/ref/spec#Struct_types) jest. Podczas osadzania podana jest tylko wartość _typ_, ale nie nazwa __. Więc 'Użytkownik' _jest_ typem. I pola 'User' są _promoted_ do struktury embedder.Ale możesz odwoływać się do wartości osadzonej, używając nazwy typu. – icza

0

Można użyć pakietu „github.com/jinzhu/copier” Kopiowanie między strukturach zawierających tę samą nazwę pola. Ten pakiet używa do tego celu refleksji.

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

Wyjście

User : John Doe [email protected] johndoe 1234 
RegistrationRequest : John Doe [email protected] johndoe 1234 
Powiązane problemy