If you haven’t heard of Golang’s not addressable concept, it doesn’t matter, it literally means that you can’t get the address of a value. Let’s start with a simple example.
m
is of type map[int]string
and contains only one key-value pair. Printing the address of the value of this key-value pair directly compiles with the error: cannot take the address of m[0]
, and cannot get the address of the value in map
. This is a relatively common example of non-addressability. The reason is also relatively simple. The map
type is implemented through a hash table, and as the number of elements of map
increases, the expansion may be triggered, then the location of the value of map
changes, i.e. its address will change, so the value of map
cannot be addressed. On the other hand, if the element does not exist in map
, it returns a zero value, which is an immutable object and cannot be addressed (immutable objects in golang are not addressable, such as constants).
For a slightly more complex example, the Golang wiki’s MethodSets has the following sentence.
The concrete value stored in an interface is not addressable, in the same way that a map element is not addressable.
It means that a concrete value assigned to an interface
type is not addressable, just like an element in a map
. Instead of understanding this statement, let’s look at an example.
|
|
defines a Male
type with two methods, a getName()
method for the value recipient and a setName()
method for the pointer recipient. In main()
, m1
is a value object of type Male
, and m2
is a pointer object of type Male
, and the getName()
and setName()
methods are called on both objects, and can be called and executed normally. Then the question arises.
m1
is a value type object (caller), why can the pointer receiver methodsetName()
be called?m2
is a pointer type object (caller), what can call the value receiver methodgetName()
?
For the first question, when the value caller calls the pointer recipient method, the compiler uses the caller’s reference (fetch address) to call the method by default, i.e., the compiler implicitly converts to (&m1).setName()
For the second problem, when a pointer caller calls a value receiver method, the compiler will by default dereference (take the value) of the pointer caller to the value type, i.e. the compiler implicitly converts to (*m2).getName()
The above example is still relatively well understood, and many books and articles explain this problem.
Then look at another example.
|
|
This example is very similar to the one just given, except that it adds a Person
type interface, defines the Male
type, implements the getName()
method for value recipients, and implements the setName()
method for pointer recipients.
Initializing the value object of Male
to assign to the Person
interface, noted as p1
, directly reports an error.
The error is that variables of type Male
cannot be assigned to Person
because type Male
does not implement the Person
interface (setName
is the pointer recipient method).
So why is it that in the previous example, the compiler can automatically take the address of the value type (non-interface type) and do an implicit conversion, but not here? The reason is the opening sentence.
The concrete value stored in an interface is not addressable.
The value type assigned to the interface is not addressable, and since it is not addressable, there is no way for the compiler to automatically take its address and pass it to the method received by the pointer.