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?
A class or struct can implement multiple interfaces, but a class can only inherit from a single class. For more information about abstract classes, see Abstract and Sealed Classes and Class Members. Interfaces can contain instance methods, properties, events, indexers, or any combination of those four member types.
Different parts of a class or struct may inherit from different interfaces.
A type can implement multiple interfaces. In the above program, we created a Motorvehicle interface with the Mileage method and a Newq interface with the AverageSpeed method. Struct type BMW implements both the methods, hence it implements both the interfaces.
Like a struct an interface is created using the type keyword, followed by a name and the keyword interface . But instead of defining fields, we define a “method set”. A method set is a list of methods that a type must have in order to “implement” the interface.
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)
}
Play it
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)
}
Play it
you will see that there are no errors! Notice how there is an &
in the object
declaration, but no *
in the i
declaration?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With