Argument Invalid Type Assertion: Non-Interface Type T on the Left

Viewed 36

I'm trying to write a generic function. In the following MWE there is a type constraint [T RestaurantEmployee], that any argument e to the function WorkAtRestaurant has to implement both the Greeter and the Cook interface.

The function shall return an object of the specific type that I provided as an argument, not only a general RestaurantEmployee which I needed to cast later on.

type Greeter interface{
    Greet()
}
type Cook interface{
    CreateATastyDish()
}

type Briton struct{} // brits can greet
func (b Briton) Greet() {
    print("Good morning")
}

// italians and french can greet AND cook
type Italian struct{}
func (i Italian) Greet(){
    print("Buon giorno")
}
func (i Italian) CreateATastyDish(){}
type French struct{}
func (f French) Greet(){
    print("Bonjour")
}
func (f French) CreateATastyDish(){}

// RestaurantEmployee s can greet their guests and create tasty dishes
type RestaurantEmployee interface{
    Greeter
    Cook
}

func WorkAtRestaurant[T RestaurantEmployee](e T) T{
    // when working at a restaurant you have to greet guests and then cook a dish
    // I simply want to call Greet and CreateATastyDish
    // it should be possible without problems because the RestaurantEmployee interface guarantees that the methods exist.
    e.(RestaurantEmployee).Greet() // <-- error: non-interface type T on the left
    e.(RestaurantEmployee).CreateATastyDish() // <-- same error message
    return e // <-- the return type shall be a specific italian or french, depending on what I provide as an argument
}

The error message is:

Non-interface type T on the left

but as far as I understand it, T is in fact an interface.

1 Answers

The RestaurantEmployee constraint might be an interface (actually all type constraints are interfaces), but T will be a concrete type when the generic WorkAtRestaurant function is instantiated and called. So e will be of a concrete type, and type assertion can only be used on interface values. But that type assertion is completely unnecessary: the type constraint ensures those methods exist, so simply use e.Greet() and e.CreateATastyDish().

func WorkAtRestaurant[T RestaurantEmployee](e T) T {
    e.Greet()
    e.CreateATastyDish()
    return e 
}

Testing it:

x := WorkAtRestaurant(French{})
fmt.Printf("\n%T", x)

This will output (try it on the Go Playground):

Bonjour
main.French
Related