Comment définir et utiliser les clôtures en golang ?

Les fonctions anonymes

Créer une fonction anonyme permet de définir une fonction dans le corps d'une autre fonction (on parle d'inline) sans avoir à la nommer. Voici un exemple qui n'a pas vraiment d'application directe, mais qui permet d'illustrer le propos (le programme affichera "salut") en avançant étape par étape :

 

Les closures

On peut utiliser ce mécanisme pour créer une clôture (en anglais, closure). D'après Wikipédia, une closure est créée lorsqu'une fonction est définie dans le corps d'une autre fonction et fait référence à des arguments ou des variables locales à la fonction dans laquelle elle est définie. Voici un exemple de code illustrant ce concept :

 

Ce code retournera le résultat suivant, ce qui montre que l'état de chacune des deux instances de la fonction compteur est unique :

1
2
3
101
102

Un autre exemple d'application

Certaines fonctions, par exemple celle qui définit le routage d'une application web, n'acceptent en paramètre une fonction n'ayant que x paramètres :

func main() {
	http.HandleFunc("/home", homeHandler)
	http.ListenAndServe(":9999", nil)
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
	p := Page{Titre: "mon premier essai"}
	err := templates.ExecuteTemplate(w, "index.html", p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

Imaginons maintenant que vous souhaitiez initialiser ce contrôleur avec un paramètre supplémentaire. Si vous vous contentez d'ajouter un paramètre dans son prototype, le compilateur retournera une erreur parce que la fonction HandleFunc n'accepte pour paramètre qu'une fonction ayant deux paramètres. L'utilisation d'une fonction anonyme permet de vous sortir de ce mauvais pas. Voici un exemple de code complet :

package main

import (
	"net/http"
	"html/template"
)

type Page struct {
	Titre	string
}

var templates = template.Must(template.ParseFiles("index.html"))

func main() {
	valeurInit := "mon premier essai"
	http.HandleFunc("/home", func(w http.ResponseWriter, r *http.Request) {
		homeHandler(w, r, valeurInit)
	})
	http.ListenAndServe(":9999", nil)
}

func homeHandler(w http.ResponseWriter, r *http.Request, titre string) {
	p := Page{Titre: titre}
	err := templates.ExecuteTemplate(w, "index.html", p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

Étiquettes :   golang   closures 
Portrait de Benjamin BALET
Benjamin BALET
Consultant APM

Retrouvez mes cooordonées

Benjamin BALET sur viadeo






Vous aimerez aussi

Les timers et les tickers avec Golang

Comment déclencher une fonction de manière périodique ou différée ? Voyons comment faire avec la bibliothèque standard.   Lire »

Canaux et go routines avec ou sans état

Exemples d'utilisation du type chan et des go routines stateful et stateless   Lire »

Comment gérer efficacement les erreurs en golang ?

Préconisations officielles pour la gestion des erreurs dans un programme golang. Cet article complète les explications sur panic, defer et recover   Lire »

Les lois de la réflexion

Une traduction du blog officiel de golang expliquant le mécanisme de la réflexion en Go.   Lire »

Types, Valeurs, variables et constantes

Cet article vous permettra de comprendre une des bases de tous les langages de programmation : Types, Valeurs, Variables et constantes en go   Lire »

Commentaires

Soyez le premier à commenter cet article

Publier un commentaires

Tous les commentaires sont soumis à modération. Les balises HTML sont pour la plupart autorisées. Les liens contextuels et intéressants sont en follow.

(requis)
(requis)
(requis, mais non publié)
(recommandé si vous souhaitez être publié)