Third rule of selectors

October 26, 2023

Selectors

  1. As an exception, if the type of x is a defined pointer type and (*x).f is a valid selector expression denoting a field (but not a method), x.f is shorthand for (*x).f.

I find this wording to be confusing. That probably means some of you do, too. So here goes my best attempt at explaining it.

“if the type of x is a defined pointer type” refers to something like this:

type Person struct { // Person is a defined type
  Name string
}

var x = &Person{} // x is of type *Person, not Person, thus it is a "defined pointer type"

Since x is a pointer, the complete, canonical way to access the Name field on x as defined above would be:

name := (*x).Name

That is to say, we have to dereference x to get at its pointed-to value. That’s what (*x) does. Then we can access the field.

What the spec is telling us is that as a shorthand for this, we can use x in place of (*x):

name := x.Name

Quotes from The Go Programming Language Specification Version of August 2, 2023


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


Illegal selectors

We’ll cover the last 3 rules of selectors in one go today, since they’re all about illegal selectors. Selectors … In all other cases, x.f is illegal. Simple enough. The cases mentioned in rules 1-3 ar ethe only valid uses of x.f. All others are illegal. var x int x.chicken // illegal! If x is of pointer type and has the value nil and x.f denotes a struct field, assigning to or evaluating x.


Type Conversion & struct tgs

We’ve already mentioned that struct tags are ignored when doing conversion between struct types. Now we see where that’s defined, along with an example: Conversions … Struct tags are ignored when comparing struct types for identity for the purpose of conversion: type Person struct { Name string Address *struct { Street string City string } } var data *struct { Name string `json:"name"` Address *struct { Street string `json:"street"` City string `json:"city"` } `json:"address"` } var person = (*Person)(data) // ignoring tags, the underlying types are identical I don’t think there’s much else to say about that, so let’s move on, and finish up this section.


Address operators

Let’s talk about addresses. Address operators For an operand x of type T, the address operation &x generates a pointer of type *T to x. The operand must be addressable, that is, 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. This leads to one of my great annoyances about the Go language.

Get daily content like this in your inbox!

Subscribe