Salt la conținutul principal
Modulul 5 · Lecția 2 din 522/50 în curs~14 min
Lecții din modul (2/5)

Metode: valoare vs receptor pointer

O metodă în Go este o funcție cu un receptor: o specială parametru declarat între func și numele metodei, care leagă metodă la un tip. Nu există clase: metodele pot fi definite orice tip numit declarat în pachetul curent.

Sintaxă

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"

Receptorul p Person face ca Greet o metodă de Person. În interiorul metoda, p este o variabilă ca oricare alta.

Receptor de valoare vs receptor pointer

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
}

Cu un receptor pointer puteți modifica receptorul și modificările sunt vizibile în afara metodei. Cu un receptor de valoare nu poți - ai face-o modificați doar copia locală.

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

Când să utilizați un receptor pointer

Reguli practice, în ordinea priorităților:

  1. Trebuie să modificați receptorul → receptor pointer. Obligatoriu.
  2. Structura este mare (zeci de câmpuri, matrice în interior) → pointer receptor pentru a evita copiile costisitoare.
  3. Consecvență: dacă MĂRÂNU o metodă de pe tip are un receptor pointer, utilizați un receptor pointer și pentru ceilalți. O convenție foarte importantă pentru interfețe (Modulul 6).
  4. Tipuri mici, imuabile, „valoare” (timp.Timp, numere complexe, mici structs) → receptor de valoare, mai lizibil.

Metode pe tipuri non-struct

Puteți defini metode pentru orice tip NAMED declarat în pachetul dvs.:

Go
type Celsius float64

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

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

Nu le puteți defini pe tipuri din alte pachete (de exemplu, int, string): trebuie mai întâi creați un tip denumit local.

Încearcă

Exercițiu#go.m5.l2.e1
Încercări: 0Se încarcă…

Adăugați o metodă de șir Greet() (receptor de valoare) la Person care returnează „ciao <Nume>”.

Se încarcă editorul...
Afișează indiciu

Receptor între paranteze ÎNAINTE de numele metodei.

Soluție disponibilă după 3 încercări

Exercițiu#go.m5.l2.e2
Încercări: 0Se încarcă…

Adăugați o metodă Rename(n string) cu un receptor POINTER care schimbă p.Name.

Se încarcă editorul...
Afișează indiciu

Receptor pointer: `(p *Persoană)`.

Soluție disponibilă după 3 încercări

Quiz#go.m5.l2.e3
Gata

Când ar trebui să utilizați un receptor pointer (p *T)?

Go
func (t ?T) M() { ... }
Opțiuni de răspuns

Recapitulare

  • Metoda = functie cu un receptor: func (r T) Name(...) ... { ... }.
  • Receptor valoric: operează pe o copie; Receptor pointer: funcționează pe original.
  • Go efectuează automat conversia T ↔ *T pe site-ul apelului.
  • Receptor pointer când: mutație + struct mare + consistență cu alte metode de acest tip.
  • Nu amestecați niciodată receptorii de valoare și indicatori pe același tip.
  • Metodele merg pe tipurile NAMED din pachetul curent (inclusiv non-struct).