Middle
Quelles sont les conséquences possibles lors de la lecture à partir d'un canal fermé en Go?
sobes.tech IA
Réponse de l'IA
La lecture d’un canal fermé renvoie immédiatement la valeur nulle du type d’éléments du canal sans blocage. Si un second paramètre booléen est présent, il sera false.
package main
import (
"fmt"
)
func main() {
ch := make(chan int, 1) // Canal tamponné
ch <- 1
close(ch)
val, ok := <-ch // Lecture d’un canal fermé
fmt.Printf("Valeur : %d, Ouvert : %t\n", val, ok) // Affichera "Valeur : 1, Ouvert : true"
val, ok = <-ch // Lecture répétée du même canal fermé
fmt.Printf("Valeur : %d, Ouvert : %t\n", val, ok) // Affichera "Valeur : 0, Ouvert : false"
// Lectures supplémentaires du canal fermé
val, ok = <-ch
fmt.Printf("Valeur : %d, Ouvert : %t\n", val, ok) // Affichera "Valeur : 0, Ouvert : false"
}
Principales conséquences :
- Obtention d’une valeur nulle : Le programme ne plantera pas, mais obtiendra la valeur nulle par défaut pour le type de données du canal.
- Indicateur de fermeture : Le second paramètre booléen, s’il est utilisé, devient
false, signalant que le canal est fermé et que la valeur reçue est nulle. - Lecture non bloquante : L’opération de lecture ne bloquera pas la goroutine.
- Pas de panic : Contrairement à l’écriture dans un canal fermé, la lecture d’un canal fermé ne provoque pas de panic.
Comparaison de la lecture de canaux ouverts et fermés :
| État du canal | Opération | Comportement | Valeur retournée (si second paramètre) |
|---|---|---|---|
| Ouvert | <-ch |
Blocage jusqu’à la réception ou la fermeture | Valeur, true |
| Ouvert | val, ok := <-ch |
Blocage jusqu’à la réception ou la fermeture | Valeur, true |
| Fermé | <-ch |
Obtention immédiate | Valeur nulle |
| Fermé | val, ok := <-ch |
Obtention immédiate | Valeur nulle, false |
L’utilisation du second paramètre booléen est la méthode recommandée pour déterminer si un élément réel a été reçu du canal ou si celui-ci est fermé.
package main
import (
"fmt"
)
func main() {
ch := make(chan int, 1)
ch <- 1
close(ch)
for {
val, ok := <-ch
if !ok {
fmt.Println("Le canal est fermé, sortie de la boucle.")
break
}
fmt.Printf("Valeur reçue : %d\n", val)
}
}
Ce comportement permet de terminer élégamment les goroutines qui lisent du canal après sa fermeture.