Golang auto referencing, not always possible to get the address of a value

Viewed 228

I am a newbie in Golang world. I was trying to understand the concept of auto referencing.

My confusion related to the below program? what is the difference between first and the second

  1. first line in function main
age(20).print()
  1. second and third line
myAge := age(20)
myAge.print()

Full program below:

package main
import "fmt"

type age uint8

func (a *age) print() {
  fmt.Println(a)
}


func main() {
  age(20).print() // this line throws error

  // however, the below line works properly
  myAge := age(20)
  myAge.print()
}

Please help to understand the difference between the two approaches. I was in an assumption they both are the same.

1 Answers

This is a convenience provided by the compiler. As mentioned in the calls section of the spec:

If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m()

This is elaborated on in the method Pointers vs Values section of Effective Go.

To determine what is addressable, you can refer to the Address operators section of the spec. Specifically:

... either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, x may also be a (possibly parenthesized) composite literal.

Going back to your example, (a *age) print() is a pointer receiver on age. This means that the full call on an age variable is &<expr>.print(). This can only be done if expr is addressable. Looking at the addressability requirements:

  • myAge is a variable, it is addressable.
  • age(20) is a type conversion and is not addressable.

Ignoring the method call, you can check the addressability easily by trying the following:

_ = &age(20)     // cannot take the address of age(20)
myAge := age(20)
_ = &myAge       // works fine
Related