Can smb explain the reason behind Interface and Fn Receiver inconsistency

Interfaces lesson: https://tour.golang.org/methods/9

“Method indirection” is inconsistent ?

TL;DR

So,
function receiver (aka method) can receive some type.
And there is a “method inderection” - one can declare to receive a pointer type,
but actual value type will work and vice versa.

However,
let us declare an interface type A with some method and lets declare this method that receives a pointer type V.
Then only a variable of pointer type V will compile successfully, and a variable of actual type V will not.
And if the method receives actual type V, then a variable of both pointer and actual types will compile
successfully with that method.

Who knows what is the reason behind this (i would say inconsistent) behavior ?

1 Like

This behavior is the result of method sets and some syntax sugar. Another response of mine explains in more detail:

Alright,

Logic behind interfaces seems reasonable enough:

  • If one implements an inteface with actual type, then calling method on pointer type will derefence -> value is copied -> no harm
  • if one implements an inteface with pointer type, then calling method is only possible on pointer type -> explicit -> no harm

But when dealing with type itself, calling a method that receives a pointer type on an actual value,
will result in silent referencing under the hood, which is a potential spot for logical bugs.

Consider an example:

package main

import "fmt"

type MyType struct {
	x int
}

func (a *MyType) inc() int {
	a.x++
	return a.x
}

func main() {
  a := MyType{1}
  a.inc()
  fmt.Println(a)
}

Here we have var a mutated which is quite inevident.

So my main concern is why not to be consistent and restrict to pass exact (actual or pointer) types everywhere ?

But haven’t you just created method functionality for your struct by doing that?

Because that would be inconvenient.

a := MyType{1}
a.inc()

is much nicer than

a := MyType{1}
(&a).inc()

With interfaces the latter is impossible because interface values are not addressable.

I would personally sucrifice a convenicence over robust code.

But now it’s settled down in my head.
An actual value of an interface type doesn’t have an address and thus cannot be referenced.

Otherwise, we would have same fancy magic for interface value as well :slight_smile:

Thanks to all.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.