# ロールを型で表現する ```go package main import ( "fmt" "reflect" ) // Define a struct type User struct { Name string Email string Roles []string } // Use the struct as an embedded field type Admin struct { User } // Define an interface type Subject interface { String() string } // Implement the interface for User func (u User) String() string { return fmt.Sprintf("%s <%s>", u.Name, u.Email) } // Use the interface func Stringify(sub Subject) string { return sub.String() } func TypeSwitch(sub Subject) { switch sub.(type) { case User: fmt.Println("sub is a User") case Admin: fmt.Println("sub is an Admin") } } func main() { user := User{ Name: "John Doe", Email: "[email protected]", Roles: []string{"user"}, } admin := Admin{ User: User{ Name: "Bob Smith", Email: "[email protected]", Roles: []string{"admin", "user"}, }, } fmt.Println(Stringify(user)) //=> John Doe <[email protected]> fmt.Println(Stringify(admin)) //=> Bob Smith <[email protected]> var sub1 Subject var sub2 Subject sub1 = user sub2 = admin fmt.Println(Stringify(sub1)) //=> John Doe <[email protected]> fmt.Println(Stringify(sub2)) //=> Bob Smith <[email protected]> fmt.Println(reflect.TypeOf(sub1)) //=> main.User fmt.Println(reflect.TypeOf(sub2)) //=> main.Admin // Type assertion if _, ok := sub1.(User); ok { fmt.Println("sub1 is a User") } if _, ok := sub1.(Admin); ok { fmt.Println("sub1 is an Admin") } // Type switch TypeSwitch(sub1) //=> sub is a User TypeSwitch(sub2) //=> sub is an Admin } ```