Набор методов которые являются интерфейсом данного типа.

Method sets любого именованного типа T состоит из всех методов с типом получателя(receiver) T.

Method sets типа указателя *T состоит из всех методов с типом получателя(receiver) T и *T.

Не разрешены методы для именованных типов, которые сами являются типами указателей:

type P *int
func (P) f() {} // ошибка компиляции

Вызов методов

Имя метода: (*Point).ScaleBy

func (p *Point) ScaleBy(factor float64) {
   p.X *= factor
   p.Y *= factor
}

Может быть вызван:

// 1
r := &Point{1; 2}
r.ScaleBy(2)
// 2
p := Point{1; 2}
pttr := &p
pttr.ScaleBy(2)
// 3
p := Point{1; 2}
(&p).ScaleBy(2)

Если получатель p является переменной типа Point, но методу необходим получатель *Point, можно использовать сокращенную запись: p.ScaleBy(2)

При которой компилятор выполнит неявное получение адреса &p этой переменной.

Это работает только для addressable переменных, включая поля структур наподобие p.X и элементы массивов или срезов наподобие perim[0].

Так же работает наоборот:

(*pttr).ScaleBy(2)
pttr.ScaleBy(2)

Элементы map

Элементы map являются не адресуемыми(not addressable). По этому получить адрес переменой и вызвать метод с получателем типа указатель нельзя. А вот наоборот, разыменовать указатель(dereference pointer) можно.

https://go.dev/play/p/LdnaJ9as_9H

package main

import (
   "fmt"
)

type Point struct{
   X float64
   Y float64
}
func (p *Point) ScaleBy(factor float64) {
   p.X *= factor
   p.Y *= factor
}
func (p Point) String() string {
   return fmt.Sprintf("X:%.2f;Y:%.2f", p.X, p.Y)
}

func main() {
   // lists := map[string]Point{}
   // lists["primes"].ScaleBy(7.7) 
   // cannot call pointer method on lists["primes"]
   // cannot take the address of lists["primes"]

   lists := map[string]*Point{}
   lists["primes"] = new(Point)
   lists["primes"].ScaleBy(7.7)
   s := lists["primes"].String()

   fmt.Println(s)
}

Интерфейсы

Значения интерфейса, так же, как у map, не адресуемое(not addressable). По этому работают те же правила.

https://play.golang.org/p/pGtW_bodOKt

package main

import (
   "fmt"
)

type Point struct{
   X float64
   Y float64
}

func (p *Point) ScaleBy(factor float64) {
   p.X *= factor
   p.Y *= factor
}

func (p Point) String() string {
   return fmt.Sprintf("X:%.2f;Y:%.2f", p.X, p.Y)
}

type Scaler interface{
   ScaleBy(float64)
}

func main() {
   p := Point{1, 2}

   // Тип значения Point
   // var s Scaler = p // Ошибка. Т.к. значения интерфейса не адресуемое, то неявно получить указатель(*Point) и использовать его method sets не получится.
   // cannot use p (type Point) as type Scaler in assignment
   // Point does not implement Scaler (ScaleBy method has pointer receiver)
   // s.ScaleBy(1.2)
   //var str fmt.Stringer  = p // Работает. У String() тип получателя Point
   //fmt.Println(str.String())

   // Тип значения *Point
   var s Scaler = &p  // Работает. У ScaleBy(float64) тип получателя *Point
   s.ScaleBy(1.2)
   var str fmt.Stringer  = &p // Работает. Есть возможность неявно разыменовать указатель и использовать method sets типа Point
   fmt.Println(str.String())
}

+----------------+-----------------------------------------------------------------------------------+
| Тип переменной   |                                   Тип получателя                                    |
|                +---------------------------+-----------------------------+-------------------------+
|                | Вызов метода у переменной    | Вызов метода у значения map     | Присваивание интерфейсу     |
+----------------+---------------------------+-----------------------------+-------------------------+
|        Т       |            T|*T           |              T              |            T            |
+----------------+---------------------------+-----------------------------+-------------------------+
|       *T       |            T|*T           |             T|*T            |           T|*T          |
+----------------+---------------------------+-----------------------------+-------------------------+

Источники