Une calculatrice est un excellent moyen de pratiquer les fonctions qui renvoient
deux valeurs : un résultat et une erreur. En Go, signaler un échec avec une
error plutôt qu’avec une panique est la manière idiomatique de gérer une
mauvaise entrée.
Énoncé
Écrivez une fonction calc(a, b int, op string) (int, error) qui applique
l’opérateur op à a et b. Prenez en charge +, -, * et /. Renvoyez
une error lorsque l’opérateur est inconnu, ou lorsqu’une division par zéro est
tentée.
Contraintes :
- La signature doit être
func calc(a, b int, op string) (int, error). - En cas de succès, renvoyez le résultat et une erreur
nil. - En cas d’échec, renvoyez
0et une erreur non nulle ; ne paniquez jamais. - Vérifiez
b == 0avant de diviser.
Exemple
calc(12, 4, "+") -> 16, <nil>
calc(12, 4, "/") -> 3, <nil>
calc(1, 0, "/") -> 0, division par zéro
calc(1, 2, "%") -> 0, opérateur inconnu : "%"
Code de départ
package main
import (
"errors"
"fmt"
)
// calc applique op ("+", "-", "*", "/") à a et b.
func calc(a, b int, op string) (int, error) {
// Renvoyez le résultat, ou une erreur pour une division par zéro
// et pour un opérateur inconnu.
return 0, nil
}
func main() {
result, err := calc(12, 4, "+")
fmt.Println(result, err)
}
Indices
Indice 1
Un switch op { ... } vous donne une branche propre par opérateur, plus un
default pour tout le reste.
Indice 2
Dans la branche "/", vérifiez if b == 0 d’abord et renvoyez une erreur comme
errors.New("division par zéro") avant de diviser.
Indice 3
Faites renvoyer au cas default un fmt.Errorf("opérateur inconnu : %q", op)
pour que l’appelant voie quel opérateur a été refusé.
Correction
Afficher la correction
package main
import (
"errors"
"fmt"
)
var errDivisionParZero = errors.New("division par zéro")
func calc(a, b int, op string) (int, error) {
switch op {
case "+":
return a + b, nil
case "-":
return a - b, nil
case "*":
return a * b, nil
case "/":
if b == 0 {
return 0, errDivisionParZero
}
return a / b, nil
default:
return 0, fmt.Errorf("opérateur inconnu : %q", op)
}
}
func main() {
for _, op := range []string{"+", "-", "*", "/"} {
result, err := calc(12, 4, op)
if err != nil {
fmt.Printf("12 %s 4 -> erreur : %v\n", op, err)
continue
}
fmt.Printf("12 %s 4 = %d\n", op, result)
}
if _, err := calc(1, 0, "/"); err != nil {
fmt.Printf("1 / 0 -> erreur : %v\n", err)
}
}calc renvoie deux valeurs, ce qui est le schéma standard en Go : le résultat
et une error valant nil lorsque tout s’est bien passé. Le switch
sélectionne une branche par opérateur. La branche "/" se protège d’un diviseur
nul avant de diviser : le programme renvoie une erreur claire au lieu de
paniquer. L’appelant teste err != nil et réagit avant de faire confiance au
résultat.
Erreurs fréquentes :
- Diviser avant de vérifier
b == 0, ce qui déclenche une panique à l’exécution. - Renvoyer
nilpour l’erreur mais un résultat sans signification : l’appelant ne peut plus distinguer le succès de l’échec. - Ignorer l’erreur à l’appel avec
result, _ := calc(...), ce qui masque les vrais problèmes.
Plongez dans le fonctionnement des paramètres et des valeurs de retour dans Les fonctions en Go.