I have the following code:
package main
type MyInterface interface {
Test()
}
type MyType struct {
}
func (m MyType) Test(){}
func AcceptInterface(i *MyInterface){
}
func main() {
object := &MyType{}
AcceptInterface(object)
}
I was expecting this to work, because MyType implements MyInterface, but I get:
cannot use object (type *MyType) as type *MyInterface in argument to AcceptInterface: *MyInterface is pointer to interface, not interface
I tried doing type assertion: object.(MyInterface), but that doesn't work either.
How can I accomplish this?
As the error says,
cannot use object (type *MyType) as type *MyInterface in argument to AcceptInterface: *MyInterface is pointer to interface, not interface
This means that it is expecting an interface
value, not a pointer.
If you change the pointers to values in your code (by removing the &
and *
), the program will run with no errors:
package main
type MyInterface interface {
Test()
}
type MyType struct {
}
func (m MyType) Test(){}
func AcceptInterface(i MyInterface){
}
func main() {
object := MyType{}
AcceptInterface(object)
}
If you still want to use a pointer as an argument, there are two important parts of the Go language to note
From the Go Spec on what exacly is a variable that fits an instance:
A variable of interface type can store a value of any type with a method set that is any superset of the interface.
From the Go Spec on what pointers being automatically dereferenced:
As with selectors, a reference to a non-interface method with a value receiver using a pointer will automatically dereference that pointer:
pt.Mv
is equivalent to(*pt).Mv
[and] as with method calls, a reference to a non-interface method with a pointer receiver using an addressable value will automatically take the address of that value:t.Mp
is equivalent to(&t).Mp.
Those two points are important, because when combined they explain that pointers to variables can still fit instances. This is because the pointer's method set is automatically dereferenced by the Go compiler (and since the variable it is referencing can fit an instance, the pointer can, too)!
In action, this means that in order to see if a pointer fits an instance, you have to declare the instance as a value and the pointer as a pointer.
If you run this code:
package main
type MyInterface interface {
Test()
}
type MyType struct {
}
func (m MyType) Test() {}
func AcceptInterface(i MyInterface) {
}
func main() {
object := &MyType{}
AcceptInterface(object)
}
you will see that there are no errors! Notice how there is an &
in the object
declaration, but no *
in the i
declaration?
type MyInterface interface {
Test()
}
type MyType struct {
}
func (m MyType) Test(){}
Note: it means that MyType
implemts the interface MyInterface
, not MyType*
.
You can use:
func (m *MyType) Test(){} //Notice here
func AcceptInterface(i *MyInterface){
}
func main() {
object := &MyType{}
AcceptInterface(object)
}
Use explicit typing if you want to pass a pointer to interface:
func main() {
var object MyInterface = MyType{}
AcceptInterface(&object)
}
I would not recommend using pointer interfaces as you would need to write code like (*i).Test()
to call the interface pointer methods. The compiler do auto dereferencing for struct pointers, not so for interface pointers.