Calculatrice en Go

Créez une petite calculatrice entière qui renvoie un résultat ou une erreur pour chaque opération, puis comparez avec une correction complète et testée.

Niveau
Intermédiaire
Temps estimé
20 min
Notions abordées
fonctions, erreurs

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 0 et une erreur non nulle ; ne paniquez jamais.
  • Vérifiez b == 0 avant 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 nil pour 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.

Recherche

La recherche s’exécute entièrement dans votre navigateur.