0

I am trying to use interfaces more in my codebase for a game server I am writing and understand the high level concept and when one should be used (I think). In my case I am using them to decouple my packages from one another amongst other as well as make testing easier.

My question boils down to I have a struct which has ptr receive methods. I am then passing this struct to another function via an interface just like in this playground I am confused as to why a function with a parameter of type interface can accept an address to something that implements that interface. Why is it not func something(f *face), what purpose does *interface serve?

John
  • 343
  • 2
  • 5
  • 15
  • Related / Possible duplicate of [How can &deployment satisfy type runtime.Object in kubernetes code?](https://stackoverflow.com/questions/48861383/how-can-deployment-satisfy-type-runtime-object-in-kubernetes-code/48861656#48861656) – icza Mar 01 '18 at 11:49
  • 1
    Rule of thumb: Never use a pointer to an interface. Pointer to interface is allowed because it is useful if a function wants to change the interface _itself_. If you do not understand this: Fine. Just do not use pointer to interface as it is not needed in 99.99% of all cases. – Volker Mar 01 '18 at 12:07
  • See my answer here, it annotates why this is a thing and addresses the common confusion surrounding interface pointers: https://stackoverflow.com/questions/44370277/type-is-pointer-to-interface-not-interface-confusion/44372954#44372954 – Kaedys Mar 01 '18 at 18:21

1 Answers1

1

It is not the case that "a parameter of type interface can accept an address to something that implements that interface". Quite the opposite.

Your concrete foo does not implement the interface face. It doesn't.

Only *foo does which is a different type in Go.

You can only assign *foo to variables of type face. (Okay, there is some sugar in Go which might let you an addressable foo to a face, but here the process of taking the pointer is automatic).

Take a look at the language spec and the type system.

Volker
  • 40,468
  • 7
  • 81
  • 87
  • I read the spec (surrounding types, methods and interface) and I was confused as to why `*foo` implements the interface but `foo` does not.My understanding of `func (receiver) Name(parms) {}` is that it's syntatic sugar for `func Name(receiver, parms) {}` and so am confused as to why the ptr to the struct implements it but the concrete does not. – John Mar 01 '18 at 12:36
  • @John Well because there is no `func Work(foo)` so there is no `func Work(foo)`. It does not matter whether you which format you choose to write down methods. The key to understanding is that `*foo` and `foo` are two totally normal but different types in Go. It is not that `foo` is a real type and *foo is some "take the address mumbo jumbo". *foo is a type like map[string][]complex128 is. *foo can have methods just as map[string][]complex128 can have methods. if *foo doesn't have method Work it cannot be assigned to face. – Volker Mar 01 '18 at 12:57
  • thanks I think I understand. I have been treating `*foo` & `foo` the same with `*` being the address of `foo` rather than a completely separate type that just so happens to be a ptr. – John Mar 01 '18 at 13:06
  • To be fair, there's a lot of syntactical sugar surrounding it. If your `Work()` method used a `(f foo)` receiver instead of a `(f *foo)` receiver, then you could pass _either_ a `foo` or a `*foo` to the interface. Method calls work the same way, you can call a pointer-receiver method on a non-pointer variable, as long as its addressable. The only place this really breaks down is that you cannot use _pointer_ methods to fulfill an interface when passing a _value_ of that type to the interface. The reverse is not the case, you _can_ use value methods to fulfill for a passed pointer. – Kaedys Mar 01 '18 at 18:26