Leçons du module (4/5)
Fermetures et fonctions comme valeurs
Dans Go, les fonctions sont des valeurs de première classe : elles peuvent être affectées à variables, transmises à d’autres fonctions et renvoyées. Une fermeture est un fonction littérale (anonyme) qui capture les variables du environnement dans lequel il est défini.
Fonction littérale
Une fonction sans nom, écrite en ligne. Vous l'appelez immédiatement ou attribuez-le :
greet := func(name string) {
fmt.Println("ciao", name)
}
greet("Anna")
// invocata immediatamente:
func() { fmt.Println("subito") }()Le type de greet est func(string).
Capturer l'environnement : clôture
La fonction littérale peut lire et modifier les variables visibles dans sa portée lexicale, même après le retour de la fonction externe :
func counter() func() int {
n := 0
return func() int {
n++
return n
}
}
c := counter()
fmt.Println(c(), c(), c()) // 1 2 3n "vit" tant qu'au moins une fermeture y fait référence. Chaque appel à
counter() crée un nouveau n indépendant.
Fermeture comme rappel
Un modèle très courant :
nums := []int{3, 1, 2}
sort.Slice(nums, func(i, j int) bool {
return nums[i] < nums[j]
})La fermeture capture nums et définit l'ordre.
Fonctions comme paramètres
Pour accepter une fonction en paramètre, écrivez son type :
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]Si la signature devient difficile à lire, définissez un type alias :
type Transform func(int) int
func apply(nums []int, f Transform) []int { ... }Essayez-le
Définissez counter() qui renvoie une fermeture : chaque appel à la fermeture s'incrémente et renvoie un compteur interne.
Afficher l'indice
`n` doit être déclaré AVANT le retour ; la fermeture le capture.
Solution disponible après 3 tentatives
Attribuez à f une fonction littérale qui imprime 'ciao', puis appelez-la.
Afficher l'indice
Syntaxe : `f := func() { ... }` puis `f()`.
Solution disponible après 3 tentatives
Qu'est-ce que cela imprime ? (attention à la portée de fermeture)
mk := func() func() int {
x := 0
return func() int { x++; return x }
}
a := mk()
b := mk()
fmt.Println(a(), a(), b())Récapitulatif
- Les fonctions sont de première classe : assignables, passables, consignées.
- Littéral de fonction :
func(params) ret { ... }, anonyme. - Fermeture : capture les variables de la portée lexicale, les maintient en vie.
- Type de fonction explicite en paramètres :
func(int) int. - Depuis Go 1.22, chaque itération for possède sa propre copie de la variable de boucle.