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ă
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
// 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ă.
p := Person{Name: "Ada"}
p.Rename("Grace")
fmt.Println(p.Name) // "Grace" — change is visibleCând să utilizați un receptor pointer
Reguli practice, în ordinea priorităților:
- Trebuie să modificați receptorul → receptor pointer. Obligatoriu.
- Structura este mare (zeci de câmpuri, matrice în interior) → pointer receptor pentru a evita copiile costisitoare.
- 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).
- 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.:
type Celsius float64
func (c Celsius) ToFahrenheit() float64 {
return float64(c)*9/5 + 32
}
t := Celsius(20)
fmt.Println(t.ToFahrenheit()) // 68Nu le puteți defini pe tipuri din alte pachete (de exemplu, int, string): trebuie
mai întâi creați un tip denumit local.
Încearcă
Adăugați o metodă de șir Greet() (receptor de valoare) la Person care returnează „ciao <Nume>”.
Afișează indiciu
Receptor între paranteze ÎNAINTE de numele metodei.
Soluție disponibilă după 3 încercări
Adăugați o metodă Rename(n string) cu un receptor POINTER care schimbă p.Name.
Afișează indiciu
Receptor pointer: `(p *Persoană)`.
Soluție disponibilă după 3 încercări
Când ar trebui să utilizați un receptor pointer (p *T)?
func (t ?T) M() { ... }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↔*Tpe 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).