Direct naar de hoofdinhoud
Module 5 · Les 2 van 522/50 in de cursus~14 min
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

Go
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

Go
// 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.

Go
p := Person{Name: "Ada"}
p.Rename("Grace")
fmt.Println(p.Name)   // "Grace" — change is visible

Wanneer moet u een pointer-ontvanger gebruiken?

Praktische regels, in volgorde van prioriteit:

  1. U moet de ontvanger aanpassen → aanwijzerontvanger. Verplicht.
  2. De structuur is groot (tientallen velden, arrays erin) → pointer ontvanger om dure kopieën te vermijden.
  3. 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).
  4. 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:

Go
type Celsius float64

func (c Celsius) ToFahrenheit() float64 {
    return float64(c)*9/5 + 32
}

t := Celsius(20)
fmt.Println(t.ToFahrenheit())  // 68

U kunt ze niet definiëren op typen uit andere pakketten (bijvoorbeeld int, string): u moet maak eerst een lokaal benoemd type.

Probeer het

Oefening#go.m5.l2.e1
Pogingen: 0Laden…

Voeg een Greet()-tekenreeksmethode (waardeontvanger) toe aan Persoon die 'ciao <Naam>' retourneert.

Editor laden…
Toon hint

Ontvanger tussen haakjes VOOR de naam van de methode.

Oplossing beschikbaar na 3 pogingen

Oefening#go.m5.l2.e2
Pogingen: 0Laden…

Voeg een Rename(n string)-methode toe met een POINTER-ontvanger die p.Name verandert.

Editor laden…
Toon hint

Aanwijzerontvanger: `(p *Persoon)`.

Oplossing beschikbaar na 3 pogingen

Quiz#go.m5.l2.e3
Klaar

Wanneer moet u een pointerontvanger (p *T) gebruiken?

Go
func (t ?T) M() { ... }
Antwoordmogelijkheden

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 ↔ *T automatisch 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).