Timeouts
#
// Les _timemouts_ (dépasser le temps d'exécution alloué)
// sont importants pour des programmes qui se connectent
// à des ressources externes ou qui doivent limiter leur
// temps d'exécution.
// Implémenter des timeout en Go est facile et élégant
// grâce aux canaux et à `select`.
package main
import "time"
import "fmt"
func main() {
// Pour notre exemple, supposons que l'on exécute un
// appel externe qui renvoie son résultat sur le
// canal `c1` après 2s.
c1 := make(chan string, 1)
go func() {
time.Sleep(time.Second * 2)
c1 <- "result 1"
}()
// Voici le `select` qui implémente le timeout.
// `res := <-c1` attend le résultat et `<-Time.After`
// attend qu'une valeur soit envoyée après 1s.
// Comme `select` traite la première réception qui
// arrive, nous prenons le cas du timeout si
// l'opération prend plus de temps qu'il ne lui
// en est alloué
select {
case res := <-c1:
fmt.Println(res)
case <-time.After(time.Second * 1):
fmt.Println("timeout 1")
}
// Si nous permettons un plus gros timeout de 3s,
// alors la réception depuis `c2` va réussir et nous
// afficherons le résultat.
c2 := make(chan string, 1)
go func() {
time.Sleep(time.Second * 2)
c2 <- "result 2"
}()
select {
case res := <-c2:
fmt.Println(res)
case <-time.After(time.Second * 3):
fmt.Println("timeout 2")
}
}
// todo: annulation?
# Lancer ce programme montre que la première opération
# timeout et que la seconde réussit.
$ go run timeouts.go
timeout 1
result 2
# Utiliser ce modèle de timeout avec `select` nécessite
# de communiquer les résultats à travers les canaux.
# C'est une bonne idée en général, car d'autres
# fonctionnalités importantes de Go sont basées sur les
# canaux et sur `select`.
# Nous allons regarder cela ensuite: timers et tickers.