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:
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:
func counter() func() int {
n := 0
return func() int {
n++
return n
}
}
c := counter()
fmt.Println(c(), c(), c()) // 1 2 3n „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:
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:
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:
type Transform func(int) int
func apply(nums []int, f Transform) []int { ... }Încearcă
Definiți counter() care returnează o închidere: fiecare apel la închidere crește și returnează un contor intern.
Afișează indiciu
`n` trebuie declarat ÎNAINTE de returnare; închiderea îl surprinde.
Soluție disponibilă după 3 încercări
Atribuiți lui f o funcție literală care afișează „ciao”, apoi apelați-o.
Afișează indiciu
Sintaxă: `f := func() { ... }` apoi `f()`.
Soluție disponibilă după 3 încercări
Ce imprimă asta? (atenție la domeniul de închidere)
mk := func() func() int {
x := 0
return func() int { x++; return x }
}
a := mk()
b := mk()
fmt.Println(a(), a(), b())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.