A value of type can also call the pointer receiver’s method!

Golang Method Sets are defined by the following rules:

Rules:

  1. The set of methods for a value of a type contains only methods declared by the value receiver

  2. The set of methods that point to Pointers of type T contains both methods declared by the value receiver and methods declared by the pointer receiver

In practice, you’ll find that a value of type can also call a pointer receiver’s method if the value of T is addressable

package main

import "fmt"

type baseImpl string

const (
	BI = baseImpl("1234"))type base interface {
	func1 ()
}

func (b *baseImpl) func1(a) {
	fmt.Println("invoke base impl func1")}func main(a) {
	bi := baseImpl("1234")
	bi.func1() // Invoke base impl func1
	BI.func1() // Cannot call a pointer method on 'BI'
}
Copy the code

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

As you can see in practice, the func1 method can be called for the value BI that defines baseImpl, because BI is addressable

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

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

What values are not addressable?

Common types of non-addressable values are:

  • constant
  • Base type value
  • Result value of operation
  • The result value of the string index expression and slice expression
  • The result value of an index expression for a dictionary
  • Functions, methods, and their calling expressions
  • Type conversion
  • assertions
package main

const (
	I = 1
)

func main(a) {
	i := &I           // Constants are not addressable
	str := &"1234"    // Basic type, unaddressable
	u := &str[0]      // String index expression, not addressable
	s := &str[1:2]    // String slice expression, non-addressable
	i2 := &int64(123) // Type strong, unaddressable

	strArr := []string{""}
	sa := &strArr[0] // Slice index expressions are addressable
}
Copy the code

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

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

Should method recipients choose a value type or a pointer type?

The pointer type receiver should be selected for the following reasons:

  1. Using pointer receivers means that you can modify the value that the receiver points to
  2. Avoid memory & performance problems caused by value replication during method calls