Use of go's struct pointer as interface

I want to pass struct method as function value. Why does compilation fail if function is required to return interface{} and it returns *struct? It perfectly works if I try to return *struct from function that is declared to return interface{} (wrapper func).

package main

func main() {
        println("hello")
        testInterface(wrapper)          // works
        instance := MyStruct{}
        testInterface(instance.works)   // works
        testInterface(instance.fails)   // fails: ./main.go:8: cannot use instance.fails (type func(int) *MyStruct) as type func(int) interface {} in argument to testInterface
}

func testInterface(f func() interface{}) {
        f()
        return
}

type MyStruct struct {
}

func (s *MyStruct) works() interface{} {
        return s
}

func (s *MyStruct) fails() *MyStruct {
        return s
}

func wrapper() interface{} {
        s := MyStruct{}
        return s.fails()

}

Upvotes: 1

Views: 258

Answers (1)

zerkms
zerkms

Reputation: 254886

That's because it does not fit the assignability criterias

A value x is assignable to a variable of type T ("x is assignable to T") in any of these cases:

  • x's type is identical to T.
  • x's type V and T have identical underlying types and at least one of V or T is not a named type.
  • T is an interface type and x implements T.
  • x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a named type.
  • x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type.
  • x is an untyped constant representable by a value of type T.

So, this explains why testInterface(instance.fails) fails: because the instance.fails is not assignable to the f func() interface{}.

Now the second question:

It perfectly works if I try to return *struct from function that is declared to return interface{} (wrapper func).

It works fine, because the value of the *struct type is assignable to the interface{} type because of:

  1. this rule of the assignability: "T is an interface type and x implements T."
  2. "A type implements any interface comprising any subset of its methods and may therefore implement several distinct interfaces. For instance, all types implement the empty interface:" (bold is mine)

References:

Upvotes: 4

Related Questions