Historique de la question:
Depuis le début, le langage Go a fourni le paquet time, au sein duquel se trouvent les principales fonctions pour gérer le temps : time.Sleep et time.After. Contrairement aux langages avec un sommeil système (System.sleep), Go implémente des minuteries asynchrones via ses primitives, ce qui est important pour le travail multi-thread.
Problème:
Souvent, les développeurs utilisent mal time.Sleep pour réaliser des pauses entre les tâches, ce qui est indésirable dans les programmes concurrents. Dans la paradigme Go, il est plus correct de gérer l'attente d'événements via des canaux et time.After pour l'intégration avec select/canaux.
Solution:
time.Sleep(d) bloque la goroutine actuelle pendant d temps, c'est un « sommeil » direct. time.After(d) retourne un canal sur lequel un événement-temps apparaîtra après d. La dernière option est beaucoup plus flexible dans select par rapport aux canaux, pratique pour les attentes interrompues et les délais.
Exemple de code :
ch := make(chan struct{}) go func() { time.Sleep(2 * time.Second) ch <- struct{}{} }() select { case <-ch: fmt.Println("fait") case <-time.After(1 * time.Second): fmt.Println("délai") }
Caractéristiques clés :
Peut-on utiliser time.Sleep pour bloquer l'exécution de tout le programme ?
Non, time.Sleep « endort » seulement une goroutine, les autres continuent à travailler.
Le time.After peut-il entraîner des fuites de mémoire si le canal n'est pas lu ?
Oui, le minuteur reste actif tant que la valeur n'est pas lue — s'il n'y a pas de lecture, le ramasse-miettes ne supprimera pas l'objet.
Exemple de code :
func leak() { for { _ = time.After(time.Hour) } }
Comment annuler correctement l’attente par time.After en cas d’absence d’événement ?
Il est préférable d'utiliser time.Timer et d'arrêter manuellement, si besoin, d'annuler l'attente avant la date limite :
t := time.NewTimer(time.Minute) if done { t.Stop() }
La goroutine attend un signal du travail, et en cas de délai fait ceci :
time.Sleep(10*time.Second) doSomething()
Avantages :
Inconvénients :
Le code est construit via select et time.After :
select { case <-workSignal: // Exécuter case <-time.After(10 * time.Second): // Faire selon le délai }
Avantages :
Inconvénients :