Reputation: 607
I was reading this blogpost http://www.hydrogen18.com/blog/golang-embedding.html and came across these lines
There is an important distinction to observe here. If myParent is an instance of Parent the value myParent cannot act as a Valueable. You must use the the value &myParent, a pointer to the instance, to act as a Valueable. This is because the method Value receives a *Parent not a Parent.
I have created a sample https://play.golang.org/p/ojTKZfx97g . So the questions is why calling the method myparent.Value() works by itself but does not work when called through interface
Upvotes: 3
Views: 1175
Reputation: 607
As per Effective Go if the value is addressable then go will automatically insert & when calling pointer receiver method.
I did further research on this and looks like my understanding what is addressable is wrong. I was thinking along the line of c++ whereas as long it is lvalue then it is addressable. But it seem that in golang not everything is addressable such as
The interesting question then is why concrete type of interface is not addressable so that golang can automatically do &. I found this https://groups.google.com/forum/#!topic/golang-nuts/-ZoCu5m0kJ4. I am quoting the answer by Steven Blenkinsop which you can find at the end
On one level, it's because the language spec says so. But ultimately, yes, it's because of a limitation on getting a pointer to pass as the receiver. You can't take the address of the value inside an interface, since its type could change (you could assign a differently typed value to the interface), among other reasons. So, if you need a pointer receiver, the pointer itself needs to be in the interface.
So the way I see for interface or map since the underlying memory address might change maybe by another thread that is why go does not automatically insert & for us as it cannot guarantee the memory address will be valid throughout the function call life cycle.
Upvotes: 1
Reputation: 417402
Your callValueable(v Valueable)
function has a parameter of type Valueable
which is an interface:
type Valueable interface {
Value() int64
}
You can pass any value to it which implements this interface. Your Parent
type does not, because even though it has a Value()
method, that method has a pointer receiver:
func (i *Parent) Value() int64{
return i.value
}
And according to the Go Language Specification (Method sets and Interface types) the method set of Parent
does not include this method, only the method set of *Parent
. Quoting from the Spec:
...The method set of any other type
T
consists of all methods declared with receiver typeT
. The method set of the corresponding pointer type*T
is the set of all methods declared with receiver*T
orT
(that is, it also contains the method set ofT
).
So the type Parent
does not implement the Valueable
interface but the type *Parent
does implement it.
So you can pass a *Parent
(a pointer to Parent
) as a Valuable
value to your method, because that implements the interface. You can easily obtain a pointer by using the address &
operator:
fmt.Println(callValueable(&myparent)) // This WORKS
Upvotes: 1