Comment organiser un projet Go avec plusieurs fichiers : sous le capot

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

Un projet Go d'un seul fichier, c'est facile. Et de dix ?

\n\n

Imaginez : vous écrivez en Go un utilitaire d'analyse de logs. Au début, tout tient dans un seul fichier main.go. Ça marche, tout va bien. Mais au bout d'une semaine, le code s'agrandit : des fonctions pour lire les fichiers, pour filtrer, pour envoyer des données dans la base de données. Un seul fichier se transforme en monstre de 2000 lignes. Ça vous dit quelque chose ?

\n\n

Ici se pose la question qui tourmente un débutant sur deux (et qui a rassemblé des milliers de vues sur Stack Overflow) : comment organiser correctement un projet Go avec plusieurs fichiers ? Pas simplement disperser le code dans des dossiers, mais faire en sorte que cela fonctionne, se compile et ne provoque pas d'erreurs comme undefined ou import cycle not allowed.

\n\n

Dans cet article, nous ne donnons pas simplement un modèle. Nous allons regarder sous le capot du compilateur Go et comprendre comment fonctionne réellement la liaison des fichiers, des packages et des modules. Vous apprendrez pourquoi go run *.go sauve parfois, et parfois non, et comment construire une architecture qui s'adapte.

\n\n

Fichier, package, module — la hiérarchie de base

\n\n

Avant de se jeter dans le code, analysons trois concepts clés. Sans eux, l'organisation d'un projet Go devient un jeu de devinettes.

\n\n
    \n
  • Fichier (.go) — c'est simplement un fichier texte avec du code. En lui-même, il ne signifie rien pour le compilateur.
  • \n
  • Package (package) — c'est un groupe logique de fichiers se trouvant dans un même répertoire. Tous les fichiers d'un dossier doivent avoir la même déclaration package. Si un dossier contient des fichiers avec des packages différents, le compilateur générera une erreur.
  • \n
  • Module (go.mod) — c'est la racine de votre projet. Il définit le nom du module, ses dépendances et les versions de Go. Un module peut contenir de nombreux packages.
  • \n
\n\n

Règle d'or : un répertoire = un package. L'exception concerne les tests, mais nous y reviendrons plus tard.

\n\n

Exemple pratique : le projet "Analyseur de logs"

\n\n

Créons un petit projet qui lit un fichier de log, filtre les lignes par mot-clé et affiche le résultat. Nous allons d'abord le faire "à l'arrache" (un seul fichier), puis le diviser correctement en plusieurs fichiers.

\n\n

Étape 1 : Tout dans un seul fichier (mauvais)

\n\n
// main.go\npackage main\n\nimport (\n    "bufio"\n    "fmt"\n    "os"\n    "strings"\n)\n\nfunc readLog(path string) ([]string, error) {\n    file, err := os.Open(path)\n    if err != nil {\n        return nil, err\n    }\n    defer file.Close()\n\n    var lines []string\n    scanner := bufio.NewScanner(file)\n    for scanner.Scan() {\n        lines = append(lines, scanner.Text())\n    }\n    return lines, scanner.Err()\n}\n\nfunc filterLines(lines []string, keyword string) []string {\n    var result []string\n    for _, line := range lines {\n        if strings.Contains(line, keyword) {\n            result = append(result, line)\n        }\n    }\n    return result\n}\n\nfunc main() {\n    lines, err := readLog("server.log")\n    if err != nil {\n        fmt.Println("Erreur :", err)\n        return\n    }\n    filtered := filterLines(lines, "ERROR")\n    for _, l := range filtered {\n        fmt.Println(l)\n    }\n}\n
\n\n

Ça marche. Mais imaginez que readLog se complexifie (besoin de support gzip, d'encodages), et que filterLines s'enrichisse d'expressions régulières. Le fichier deviendra illisible.

\n\n

Étape 2 : Découpage en packages (correct)

\n\n

Créons la structure de répertoires :

\n\n
log-analyzer/\n├── go.mod\n├── main.go\n└── pkg/\n    └── logreader/\n        ├── reader.go\n        └── filter.go\n
\n\n

Initialisons le module :

\n\n
go mod init log-analyzer
\n\n

Écrivons maintenant le code du package logreader. Notez que tous les fichiers dans le dossier pkg/logreader/ ont package logreader.

\n\n

pkg/logreader/reader.go

\n\n
package logread                

Blogs

Book Recommendations