Salt la conținutul principal
Modulul 3 · Lecția 4 din 514/50 în curs~12 min
Lecții din modul (4/5)

Închideri și funcții ca valori

În Go, funcțiile sunt valori de primă clasă: le pot fi atribuite variabile, transmise altor funcții și returnate. O închidere este a funcția literală (anonimă) care capturează variabilele mediul în care este definit.

Funcția literală

O funcție fără nume, scrisă în linie. O suni imediat sau atribuie:

Go
greet := func(name string) {
    fmt.Println("ciao", name)
}
greet("Anna")

// invocata immediatamente:
func() { fmt.Println("subito") }()

Tipul de greet este func(string).

Captarea mediului: închidere

Funcția literală poate citește și modifica variabilele vizibile în domeniul său lexical, chiar și după ce funcția exterioară a returnat:

Go
func counter() func() int {
    n := 0
    return func() int {
        n++
        return n
    }
}

c := counter()
fmt.Println(c(), c(), c())  // 1 2 3

n „trăiește” atâta timp cât cel puțin o închidere face referire la aceasta. Fiecare apel către counter() creează o nouă n independentă.

Închidere ca apel invers

Un model foarte comun:

Go
nums := []int{3, 1, 2}
sort.Slice(nums, func(i, j int) bool {
    return nums[i] < nums[j]
})

Închiderea captează nums și definește comanda.

Funcționează ca parametri

Pentru a accepta o funcție ca parametru, scrieți tipul acesteia:

Go
func apply(nums []int, f func(int) int) []int {
    out := make([]int, len(nums))
    for i, n := range nums {
        out[i] = f(n)
    }
    return out
}

double := func(x int) int { return x * 2 }
apply([]int{1, 2, 3}, double)   // [2 4 6]

Dacă semnătura devine greu de citit, definiți un alias de tip:

Go
type Transform func(int) int
func apply(nums []int, f Transform) []int { ... }

Încearcă

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

Definiți counter() care returnează o închidere: fiecare apel la închidere crește și returnează un contor intern.

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

`n` trebuie declarat ÎNAINTE de returnare; închiderea îl surprinde.

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

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

Atribuiți lui f o funcție literală care afișează „ciao”, apoi apelați-o.

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

Sintaxă: `f := func() { ... }` apoi `f()`.

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

Quiz#go.m3.l4.e3
Gata

Ce imprimă asta? (atenție la domeniul de închidere)

Go
mk := func() func() int {
    x := 0
    return func() int { x++; return x }
}
a := mk()
b := mk()
fmt.Println(a(), a(), b())
Opțiuni de răspuns

Recapitulare

  • Funcțiile sunt de primă clasă: atribuibile, acceptabile, returnabile.
  • Funcție literală: func(params) ret { ... }, anonim.
  • Închidere: captează variabilele domeniului lexical, le menține în viață.
  • Tip de funcție explicit în parametri: func(int) int.
  • De la Go 1.22, fiecare iterație for are propria copie a variabilei buclei.