metode în Go

Funcții legate de un tip prin receptor; cu receptor pointer pot modifica valoarea pe care sunt apelate.

Sintaxă
func (r Tip) Metoda(args) rezultat { ... }    // receptor valoare
func (r *Tip) Metoda(args) rezultat { ... }   // receptor pointer

Ce face metode

O metodă este o funcție cu un parametru special, receptorul, scris între paranteze înaintea numelui: func (c Cerc) Aria() float64. Se apelează cu punct: c.Aria(). Metode se pot adăuga oricărui tip definit în același pachet, nu doar struct-urilor (type Lei float64 poate avea metode).

Cu receptor valoare ((c Cerc)) metoda lucrează pe o copie. Cu receptor pointer ((c *Cont)) metoda poate modifica originalul și evită copierea. Regula practică: dacă vreo metodă trebuie să modifice valoarea, folosește receptor pointer la toate metodele tipului.

Go face automat conversia la apel: pe o variabilă c poți apela o metodă cu receptor pointer (c.Depune(10) devine (&c).Depune(10)). Metodele determină ce interfețe implementează un tip; o metodă String() string schimbă felul în care fmt afișează valoarea.

Exemple

Exemplul 1: Receptor valoare și receptor pointer

Depune modifică soldul pentru că primește pointer; Descriere doar citește.

package main

import "fmt"

type Cont struct {
    Titular string
    Sold    float64
}

func (c *Cont) Depune(suma float64) {
    c.Sold += suma
}

func (c *Cont) Retrage(suma float64) bool {
    if suma > c.Sold {
        return false
    }
    c.Sold -= suma
    return true
}

func (c Cont) Descriere() string {
    return fmt.Sprintf("%s: %.2f lei", c.Titular, c.Sold)
}

func main() {
    c := Cont{Titular: "Ana"}
    c.Depune(300)
    fmt.Println(c.Retrage(500), c.Retrage(120))
    fmt.Println(c.Descriere())
}

Rezultat

false true
Ana: 180.00 lei

Exemplul 2: Metoda String() și metode pe tipuri simple

fmt apelează automat String() la afișare.

package main

import "fmt"

type Temperatura float64

func (t Temperatura) Fahrenheit() float64 {
    return float64(t)*9/5 + 32
}

func (t Temperatura) String() string {
    return fmt.Sprintf("%.1f °C", float64(t))
}

func main() {
    azi := Temperatura(23.5)
    fmt.Println("azi:", azi)
    fmt.Println("în Fahrenheit:", azi.Fahrenheit())
}

Rezultat

azi: 23.5 °C
în Fahrenheit: 74.3

Greșeli frecvente

  • Receptor valoare la o metodă care trebuie să modifice: schimbarea se face pe copie și se pierde.
  • Amestecarea receptorilor valoare și pointer pe același tip: poate face ca doar *T (nu și T) să implementeze o interfață.
  • Metode pentru tipuri din alt pachet: cannot define new methods on non-local type string.
  • String() care apelează fmt.Sprint(t) pe același tip: recursivitate infinită.

Comenzi înrudite

  • struct și struct-uri: Grupează mai multe câmpuri cu nume și tipuri diferite într-un singur tip; baza pentru modelarea datelor în Go.
  • interface și interfețe: Interfața descrie un set de metode; orice tip care le are o implementează automat, fără declarație explicită.
  • pointeri (* și &): Un pointer (*T) ține adresa unei variabile; prin el funcțiile pot modifica valoarea originală.
  • embedding (încorporare): Include un tip în altul fără nume de câmp; câmpurile și metodele lui devin accesibile direct (compoziție).