Modulelessen (2/5)
Methoden: waarde versus aanwijzerontvanger
Een methode in Go is een functie met een ontvanger: een special
parameter gedeclareerd tussen func en de naam van de methode, die de
methode naar een type. Er zijn geen klassen: er kunnen methoden op worden gedefinieerd
elk benoemd type dat in het huidige pakket is gedeclareerd.
Syntaxis
type Person struct {
Name string
}
func (p Person) Greet() string {
return "ciao " + p.Name
}
p := Person{Name: "Ada"}
fmt.Println(p.Greet()) // "ciao Ada"De ontvanger p Person maakt van Greet een methode van Person. Binnen de
methode, p is een variabele zoals elke andere.
Waardeontvanger versus aanwijzerontvanger
// VALUE receiver: operates on a COPY of the value
func (p Person) NameUpper() string {
return strings.ToUpper(p.Name)
}
// POINTER receiver: operates on the original value, can mutate it
func (p *Person) Rename(n string) {
p.Name = n
}Met een pointer-ontvanger kunt u de ontvanger aanpassen en de wijzigingen zijn buiten de methode zichtbaar. Met een waardeontvanger kun je dat niet doen wijzig alleen de lokale kopie.
p := Person{Name: "Ada"}
p.Rename("Grace")
fmt.Println(p.Name) // "Grace" — change is visibleWanneer moet u een pointer-ontvanger gebruiken?
Praktische regels, in volgorde van prioriteit:
- U moet de ontvanger aanpassen → aanwijzerontvanger. Verplicht.
- De structuur is groot (tientallen velden, arrays erin) → pointer ontvanger om dure kopieën te vermijden.
- Consistentie: als TEN MINSTE één methode van het type een pointerontvanger heeft, gebruik dan een pointer-ontvanger voor de anderen ook. Een zeer belangrijke conventie voor interfaces (Module 6).
- Kleine, onveranderlijke 'waarde'-typen (tijd, tijd, complexe getallen, klein structs) → waardeontvanger, beter leesbaar.
Methoden voor niet-struct-typen
U kunt methoden definiëren voor elk NAMED-type dat in uw pakket is gedeclareerd:
type Celsius float64
func (c Celsius) ToFahrenheit() float64 {
return float64(c)*9/5 + 32
}
t := Celsius(20)
fmt.Println(t.ToFahrenheit()) // 68U kunt ze niet definiëren op typen uit andere pakketten (bijvoorbeeld int, string): u moet
maak eerst een lokaal benoemd type.
Probeer het
Voeg een Greet()-tekenreeksmethode (waardeontvanger) toe aan Persoon die 'ciao <Naam>' retourneert.
Toon hint
Ontvanger tussen haakjes VOOR de naam van de methode.
Oplossing beschikbaar na 3 pogingen
Voeg een Rename(n string)-methode toe met een POINTER-ontvanger die p.Name verandert.
Toon hint
Aanwijzerontvanger: `(p *Persoon)`.
Oplossing beschikbaar na 3 pogingen
Wanneer moet u een pointerontvanger (p *T) gebruiken?
func (t ?T) M() { ... }Samenvatten
- Methode = functie met een ontvanger:
func (r T) Name(...) ... { ... }. - Waardeontvanger: werkt op een kopie; Aanwijzerontvanger: werkt op het origineel.
- Go voert de conversie
T↔*Tautomatisch uit op de oproeplocatie. - Aanwijzerontvanger wanneer: mutatie + grote structuur + consistentie met andere methoden van het type.
- Combineer nooit waarde- en pointerontvangers van hetzelfde type.
- Methoden gaan door met NAMED-typen in het huidige pakket (inclusief niet-struct).