Odbiornik i interfejs

Metody z odbiornikami wartości mogą być wywoływane zarówno przy użyciu wartości, jak i wskaźników.

Metody z odbiornikami wskaźników mogą być wywoływane tylko przy użyciu wskaźników lub wartości dostępnych pod adresem.

Na przykład,

type S struct {
  data string
}

func (s S) Read() string {
  return s.data
}

func (s *S) Write(str string) {
  s.data = str
}

sVals := map[int]S{1: {"A"}}

// Możesz wywołać Read tylko przy użyciu wartości
sVals[1].Read()

// To nie skompiluje się:
// sVals[1].Write("test")

sPtrs := map[int]*S{1: {"A"}}

// Zarówno metoda Read, jak i Write mogą być wywoływane przy użyciu wskaźnika
sPtrs[1].Read()
sPtrs[1].Write("test")

Podobnie, nawet jeśli metoda ma odbiornik wartości, może ona spełniać interfejs przy użyciu odbiornika wskaźnika.

type F interface {
  f()
}

type S1 struct{}

func (s S1) f() {}

type S2 struct{}

func (s *S2) f() {}

s1Val := S1{}
s1Ptr := &S1{}
s2Val := S2{}
s2Ptr := &S2{}

var i F
i = s1Val
i = s1Ptr
i = s2Ptr

// Następujący kod nie skompiluje się, ponieważ s2Val jest wartością, a metoda f typu S2 nie ma odbiornika wartości
// i = s2Val

Wydajny Go zawiera doskonałe wyjaśnienia dotyczące wskaźników kontra wartości.

Dodatkowe uwagi:

  • Typ może mieć zestaw metod z odbiornikami wartości oraz zestaw metod z odbiornikami wskaźników
    • Zestaw metod z odbiornikami wartości jest podzbiorem zestawu metod z odbiornikami wskaźników, ale nie odwrotnie
  • Zasady
    • Obiekty wartości mogą używać wyłącznie zestawu metod z odbiornikami wartości
    • Obiekty wskaźników mogą używać zestawu metod z odbiornikami wartości + zestawu metod z odbiornikami wskaźników
  • Dopasowanie interfejsu (lub implementacja)
    • Typ pasuje do interfejsu, jeśli implementuje wszystkie metody interfejsu
    • Konkretnie, zestaw metod wartości typu pasuje do interfejsu lub zestaw metod wskaźników pasuje do interfejsu

Istnieją dwie konkretne metody dopasowywania:

  • Zestaw metod wartości dopasowujący interfejs
    • Można przypisać obiekt wartości lub wskaźnik do zmiennej interfejsu, ponieważ oba zawierają zestaw metod wartości
  • Zestaw metod wskaźników dopasowujący interfejs
    • Do zmiennej interfejsu możemy przypisać jedynie obiekt wskaźnika, ponieważ tylko zestaw metod wskaźników pasuje do interfejsu
    • Jeśli obiekt wartości zostanie przypisany do zmiennej interfejsu, podczas kompilacji zostanie uruchomiony mechanizm sprawdzania poprawności interfejsu

Co do przyczyny, dla której i = s2Val wywołuje błąd, dzieje się tak, ponieważ zestaw metod wartości i interfejs nie pasują.