The value of the type can also call the method of the pointer receiver!

For those of you who have studied the Method section in Golang, you must be familiar with the concept of Method Set, and you must be familiar with the above diagram. Method Set is defined by the following rules:

Rules:

  1. The set of methods for a value of type contains only the methods declared by the value receiver
  2. The set of methods that point to a pointer of type T contains both the methods declared by the value receiver and those declared by the pointer receiver

In practice, if the value of T is addressable, the value of the type can also call the method of the pointer receiver

package main import "fmt" type baseImpl string const ( BI = baseImpl("1234") ) type base interface { func1 () } func (b * BaseImpl) func1() {fmt.println ("invoke base impl func1")} func main() {bi := BaseImpl ("1234") bi.func1() // Invoke base impl func1 bi.func1 () // Cannot call a pointer method on 'BI'}

In the code above, we define an interface, Base, and its implementation class, BaseImpl, which is a method that implements the interface definition in the form of a pointer receiver

As you can see in practice, the value Bi defining BaseImpl can be used to call the Func1 method because Bi is addressable

However, because the constant BI is non-addressable, it follows the rule that the func1 method cannot be called

Thus, for addressable values, the range of the method set includes the receiver type being the value type and the pointer type; For non-addressable values, the scope of the method set includes only value type receivers

What value is not addressable?

Common types of non-addressable values are:

  • constant
  • Basic type value
  • Operation result value
  • The result value of a string index expression and a slice expression
  • The result value of the dictionary index expression
  • Functions, methods, and their calling expressions
  • Type conversion
  • assertions
Package main const (I = 1) func main() {I := &i // Constant non-addressable STR := &"1234" // Primary type, non-addressable u := &str[0] // String index expression, I2 := &int64(123) // Unaddressable s := &int64(123) Nonaddressable strArr := []string{""} sa := &strArr[0] // The index expression for slicing is addressable}

In general, immutable, temporary, and insecure are not addressable

  • Immutable: as a constant
  • Temporary results: such as the result of the operation value, index expression, slice expression (except the index expression of slice), etc
  • Unsafe: dictionary index expressions, functions, methods, etc

Should the method receiver choose a value type or a pointer type?

A pointer type receiver should be selected for:

  1. Using a pointer receiver implies support for modifying the value to which the receiver points
  2. Avoid the memory & performance issues associated with value copying during method calls