Code review en Go : ce qu'il faut vérifier pour que le code ne plante pas

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Code review en Go : ce qu'il faut vérifier pour que le code ne plante pas

\n\n

La code review — ce n'est pas juste une case à cocher dans Jira ou une occasion de se disputer avec un collègue dans les commentaires d'une pull request. C'est sans doute le moyen le plus honnête de ne pas se tirer une balle dans le pied en production. Et quand il s'agit de Go — un langage adoré pour sa simplicité et détesté pour « où sont les generics ? » (spoiler : ils existent désormais) — la relecture devient un art. Dans cet article, nous allons voir exactement quoi regarder lors d'une code review en Go, pour que votre code non seulement fonctionne, mais soit aussi agréable à l'œil. C'est parti !

\n\n

1. Gestion des erreurs : n'ignorez pas, n'ayez pas peur

\n\n

En Go, il n'y a pas d'exceptions. Tout est honnête : si une fonction peut échouer, elle retourne error. Le problème le plus fréquent chez les débutants est d'ignorer les erreurs avec un underscore. Rappelez-vous : « Never ignore an error » — ce n'est pas juste un mantra, c'est une loi.

\n\n

Que vérifier dans le code :

\n
    \n
  • Vérification err != nil — elle doit être présente partout où une fonction retourne une erreur. Même si vous êtes sûr qu'« il n'y aura pas d'erreur ici ».
  • \n
  • Journalisation ou propagation — l'erreur doit être soit journalisée avec contexte, soit remontée. L'étouffer est un mauvais comportement.
  • \n
  • Comparaison avec les erreurs sentinelles — utilisez errors.Is() et errors.As(), pas une comparaison directe avec ==.
  • \n
\n\n
// Mauvais : on ignore l'erreur\nfile, _ := os.Open("config.yaml")\n\n// Bon : on vérifie et on journalise\nfile, err := os.Open("config.yaml")\nif err != nil {\n    log.Printf("impossible d'ouvrir la config : %v", err)\n    return err\n}\ndefer file.Close()\n
\n\n

2. Goroutines et concurrence : l'ordre dans le chaos

\n\n

Les goroutines sont le superpouvoir de Go. Mais un grand pouvoir implique une grande responsabilité. Lors des relectures, on voit souvent des fuites de goroutines, des conditions de course et des blocages. Une code review en Go sans vérifier la concurrence, c'est comme conduire une voiture de sport sans ceinture de sécurité.

\n\n

Checklist pour les goroutines :

\n
    \n
  • Lancement des goroutines — contrôlez toujours leur durée de vie. Utilisez sync.WaitGroup ou des contextes.
  • \n
  • Conditions de course — vérifiez que l'accès aux données partagées est protégé par un mutex ou un canal. Lancez go test -race.
  • \n
  • Panique dans une goroutine — si une goroutine panique, tout le programme plante. En production, utilisez impérativement recover.
  • \n
\n\n
// Mauvais : goroutine sans contrôle\ngo func() {\n    // peut planter et tuer tout le processus\n    doWork()\n}()\n\n// Bon : avec WaitGroup et recover\nvar wg sync.WaitGroup\nwg.Add(1)\ngo func() {\n    defer wg.Done()\n    defer func() {\n        if r := recover(); r != nil {\n            log.Printf("goroutine plantée : %v", r)\n        }\n    }()\n    doWork()\n}()\nwg.Wait()\n
\n\n

3. Interfaces : petites et pertinentes

\n\n

En Go, les interfaces sont des contrats. Mais contrairement à Java, elles n'ont pas besoin d'être énormes. Dans la communauté Go, il y a un principe : « Plus l'interface est petite, mieux c'est ». Une méthode — idéal. Deux — normal. Trois — déjà suspect.

\n\n

Sur quoi regarder :

\n
    \n
  • Taille de l'interface — si elle a plus de 3-4 méthodes, envisagez de la diviser.
  • \n
  • Acceptez des interfaces, retournez des structures — la sagesse classique de Go. Cela rend le code flexible et testable.
  • \n
  • Ne définissez pas les interfaces à l'avance — laissez le consommateur les créer, pas le producteur.
  • \n
\n\n
// Mauvais : interface énorme\ntype Storage interface {\n    Save(data []byte) error\n    Load(id string) ([]byte, error)\n    Delete(id string) error\n    List() ([]string, error)\n    Connect() error\n    Close() error\n}\n\n// Bon : petites interfaces\ntype Saver interface {\n    Save(data []byte) error\n}\ntype Loader interface {\n    Load(id string) ([]byte, error)\n}\n

                
                

Blogs

Book Recommendations