Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass struct for function that accepts a interface

Tags:

go

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?

like image 823
lucaswxp Avatar asked Jan 17 '17 01:01

lucaswxp


People also ask

Can a struct implement an interface?

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.

Can struct inherit from interface C#?

Different parts of a class or struct may inherit from different interfaces.

Can a struct implement an interface Golang?

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.

What is interface struct?

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.


1 Answers

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

Edit 1

If you still want to use a pointer as an argument, there are two important parts of the Go language to note

  1. 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.

  2. 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?

like image 100
Marco Avatar answered Sep 28 '22 01:09

Marco