I'm confused as to why this fails to compile with:
impossible type assertion: Faz does not implement Foo (Bar method has pointer receiver)
if I make the receiver for Faz.Bar a Faz value rather than a Faz pointer then it compiles fine, but I thought it was always better to have pointer receivers so values aren't being copied around?
package main import ( "log" ) func main() { foo := New().(Faz) log.Println(foo) } type Foo interface { Bar() string } func New() Foo { return &Faz{} } type Faz struct { } func (f *Faz) Bar() string { return `Bar` }
In the overwhelming majority of cases, a pointer to an interface reflects a misunderstanding of how interfaces are supposed to work. However, there is a limitation on interfaces. If you pass a structure directly into an interface, only value methods of that type (ie.
A pointer to the value must be used, whose method set will include the method with the pointer receiver. Or the receiver type must be changed to non-pointer, so the method set of the non-pointer concrete type will also contain the method (and thus satisfy the interface).
Since the interface is a type just like a struct, we can create a variable of its type. In the above case, we can create a variable s of type interface Shape .
Interfaces in Go allow us to treat different types as the same data type temporarily because both types implement the same kind of behavior. They're central to a Go programmer's toolbelt and are often used improperly by new Go developers, which leads to unreadable and often buggy code.
Because it's *Faz
not Faz
.
func main() { foo := New().(*Faz) log.Println(foo) }
I think the answer to this question needs to a more retrospective approach towards the grammar, and how would implement it through software engineering. (Excuse the over simplification)
First a quick flashback of what are types
?
They are just memory blocks with compiler logic on top. What makes an array
different from a string
is what the compiler allows us to do with those memory blocks. (Think deeper and you may begin to realize the true difference between strongly typed
and dynamically typed
languages.)
Now next you need to realize that pointers are their own types per say. *variable
is a different memory block (aka type) than variable
. It's just that the compiler always assumes that content of *variable
is always going to be an address to a memory block of type to the right of the declaration along with other restriction/features it imposes.
Then let's recap what an interface is.
Pseudo-scientific definition: A set of requirements for any first class citizen to be of a specific type. Translated to software engineering- any block of memory (types) that has the same memory structure (think back to structure packing) associated to it as described in a contract (interface
) can be passed around as with the type name that the contract mentions.
Now you may begin to realize that when you say
func (f *Faz) Bar() string
is f
's block of memory holding a function, where f
's type is a pointer to Faz
where areas
func (f Faz) Bar() string
is f
's block of memory, where f
's type is Faz
So when you are saying that a variable of *Faz
type is satisfying a contract, then how can you assume that a variable of Faz
type will qualify as interface type in the code? Chose who satisfies your contract, and only that type can assume the interface type in your code.
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