Clean Code en Go : principes pour écrire un code lisible et maintenable
Le code propre n'est pas un luxe, mais une nécessité pour tout projet sérieux. En Go, un langage réputé pour sa simplicité et sa concision, les principes du Clean Code sont particulièrement importants. Un code mal écrit en Go devient rapidement illisible et difficile à maintenir, malgré tous les avantages du langage. Dans cet article, nous allons analyser les principes fondamentaux pour écrire un code propre en Go avec des exemples concrets.
1. Nommage correct : la base de la lisibilité
En Go, la règle est la suivante : plus la portée est petite, plus le nom est court. Cependant, cela ne signifie pas qu'il faut utiliser des variables à une seule lettre partout. Regardons des exemples.
Mauvais (code illisible) :
func f(x int, y int) int { z := x + y return z}Bon (code propre) :
func Sum(a int, b int) int { result := a + b return result}Règles importantes de nommage en Go :
- Variables : utilisez le camelCase (par exemple,
userName,totalCount) - Fonctions et types exportés (publics) : avec une majuscule —
func CalculateTax() - Non exportés (privés) : avec une minuscule —
func parseInput() - Abréviations : écrivez-les en majuscules (par exemple,
HTTPHandler, et nonHttpHandler) - Évitez la notation hongroise : n'écrivez pas
strNameouintCount— le type est déjà évident
2. Gestion des erreurs : explicite et concise
Go n'utilise pas d'exceptions — les erreurs sont retournées comme des valeurs. Un code propre exige une gestion explicite de chaque erreur. Ne les ignorez pas !
Mauvais (ignorer l'erreur) :
file, _ := os.Open("data.txt")// Erreur perdue !Bon (gestion explicite) :
file, err := os.Open("data.txt")if err != nil { log.Fatalf("Impossible d'ouvrir le fichier : %v", err)}defer file.Close()Conseils supplémentaires :
- Vérifiez toujours
err != nilimmédiatement après l'appel de la fonction - Utilisez
deferpour fermer les ressources - Créez vos propres types d'erreurs avec
fmt.Errorf("contexte : %w", err) - N'utilisez pas la panique (
panic) pour les erreurs courantes — c'est une situation exceptionnelle
3. Fonctions : courtes et avec une seule responsabilité
Le principe de responsabilité unique (Single Responsibility Principle) s'applique également aux fonctions. Chaque fonction ne doit faire qu'une seule chose.
Mauvais (la fonction fait trop de choses) :
func ProcessUserData(userID int) (string, error) { // 1. Connexion à la base de données db, _ := sql.Open("postgres", "...") // 2. Requête de données row := db.QueryRow("SELECT name, email FROM users WHERE id = ?", userID) // 3. Formatage var name, email string row.Scan(&name, &email) result := fmt.Sprintf("Nom : %s, Email : %s", name, email) // 4. Envoi d'email (effet secondaire !) sendEmail(email, "Salutation") return result, nil}Bon (division en petites fonctions) :
func GetUserName(db *sql.DB, userID int) (string, error) { var name string err := db.QueryRow("SELECT name FROM users WHERE id = ?", userID).Scan(&name) return name, err}
func FormatUserInfo(name, email string) string { return fmt.Sprintf("Nom : %s, Email : %s", name, email)}
func ProcessUserData(db *sql.DB, userID int) (string, error) { name, err := GetUserName(db, userID) if err != nil { return "", fmt.Errorf("erreur lors de la récupération de l'utilisateur : %w", err) } email, _ := getUserEmail(db, userID) /