I've been reading about type alias and composed structs in Golang. I want to be able to have two structs which are structurally identical but can be easily converted between each other.
I have a parent structure defined as:
type User struct {
Email string `json:"email"`
Password string `json:"password"`
}
And a composed struct defined as:
type PublicUser struct {
*User
}
I would expect that if I define a User
:
a := User{
Email: "admin@example.net",
Password: "1234",
}
I could then perform the following type conversion:
b := (a).(PublicUser)
But it fails with an invalid type assertion:
invalid type assertion: a.(PublicUser) (non-interface type User on left)
How can I convert between structurally similar types in Go?
Type assertions in Go let you tap into an interface's concrete type, not into structs:
A type assertion provides access to an interface value's underlying concrete value.
https://tour.golang.org/methods/15
However, with slight modifications, this code works and probably behaves as you would expect:
package main
import (
"fmt"
)
type User struct {
Email string `json:"email"`
Password string `json:"password"`
}
type PublicUser User
func main() {
a := User{
Email: "admin@example.net",
Password: "1234",
}
fmt.Printf("%#v
", a)
// out: User{Email:"admin@example.net", Password:"1234"}
b := PublicUser(a)
fmt.Printf("%#v", b)
// out PublicUser{Email:"admin@example.net", Password:"1234"}
}
Here, PublicUser
is a redefinition of the User
type; most importantly, it is a standalone type, shares the fields, but not the method set of User (https://golang.org/ref/spec#Type_definitions).
Then, you can simply use the PublicUser type constructor, as you might have been doing similarly with string
/[]byte
conversions: foo := []byte("foobar")
.
If, on the other hand, you were to use an actual type alias (type PublicUser = User
) your output will list User
as type for both instances: PublicUser is only a new name for the old thing, not a new type.