web-dev-qa-db-fra.com

Quelle est la bonne façon de mettre en page un projet Go?

J'ai un projet de go qui commence à devenir plus complexe et que je veux mettre en place le système de fichiers de manière à réduire la douleur.

Existe-t-il de bons exemples de ce qui a du sens?

105
aussiegeek

Mise à jour de mai 2013: la documentation officielle se trouve dans la section " Code organisation "

Le code Go doit être conservé dans un espace de travail .
Un espace de travail est une hiérarchie de répertoires avec trois répertoires à la racine:

  • src contient des fichiers source Go organisés en packages (un package par répertoire),
  • pkg contient des objets de package, et
  • bin contient des commandes exécutables.

go tool Crée les packages source et installe les fichiers binaires résultants dans les répertoires pkg et bin.

Le sous-répertoire src contient généralement plusieurs référentiels de contrôle de version (tels que ceux de Git ou de Mercurial) qui suivent le développement d’un ou de plusieurs packages source.

bin/
    streak                         # command executable
    todo                           # command executable
pkg/
    linux_AMD64/
        code.google.com/p/goauth2/
            oauth.a                # package object
        github.com/nf/todo/
            task.a                 # package object
src/
    code.google.com/p/goauth2/
        .hg/                       # Mercurial repository metadata
        oauth/
            oauth.go               # package source
            oauth_test.go          # test source

Mise à jour de juillet 2014: voir " Structuration d'applications en Go " dans Ben Johnson

Cet article contient des astuces telles que:

Séparez votre binaire de votre application

la combinaison du fichier main.go et de la logique de mon application dans le même package a deux conséquences:

  • Cela rend mon application inutilisable en tant que bibliothèque.
  • Je ne peux avoir qu'un seul binaire d'application.

Le meilleur moyen que j’ai trouvé de résoudre ce problème est d’utiliser simplement un répertoire "cmd" dans mon projet, où chacun de ses sous-répertoires est un binaire d’application.

camlistore/
  cmd/
    camget/
      main.go
    cammount/
      main.go
    camput/
      main.go
    camtool/
      main.go

Développement dirigé par la bibliothèque

Déplacer le fichier main.go Hors de votre racine vous permet de construire votre application du point de vue d'une bibliothèque. Le binaire de votre application est simplement un client de la bibliothèque de votre application.

Parfois, vous souhaiterez peut-être que les utilisateurs interagissent de plusieurs manières afin de créer plusieurs fichiers binaires.
Par exemple, si vous avez un package “adder” permettant aux utilisateurs d’ajouter des chiffres, vous pouvez publier une version en ligne de commande ainsi qu’une version Web.
Vous pouvez facilement le faire en organisant votre projet comme suit:

adder/
  adder.go
  cmd/
    adder/
      main.go
    adder-server/
      main.go

Les utilisateurs peuvent installer vos applications binaires "additionneur" avec "get get" à l'aide d'un Ellipsis:

$ go get github.com/benbjohnson/adder/...

Et voila, votre utilisateur a “adder” et “adder-server” Installé!

Ne devenez pas fou avec les sous-packages

Habituellement, les types de mon projet sont tous très liés, de sorte qu’il s’adapte mieux du point de vue de la convivialité et des API.
Ces types peuvent également tirer parti d'appels non exportés entre eux, ce qui permet à l'API de rester petite et claire.

  1. Regroupez les types et codes associés dans chaque fichier. Si vos types et fonctions sont bien organisés, je trouve que les fichiers ont généralement une taille comprise entre 200 et 500 SLOC. Cela peut sembler beaucoup, mais je trouve qu'il est facile de naviguer. 1000 SLOC est généralement ma limite supérieure pour un seul fichier.
  2. Organisez le type le plus important en haut du fichier et ajoutez-en une importance décroissante vers le bas du fichier.
  3. Une fois que votre application commence à dépasser 10 000 SLOC, vous devez évaluer sérieusement si elle peut être divisée en projets plus petits.

Remarque: cette dernière pratique n'est pas toujours bonne:

Désolé, je ne peux pas accepter cette pratique.
La séparation des types en fichiers facilite la gestion du code, la lisibilité, la maintenabilité, la testabilité.
Cela peut également garantir une responsabilité unique et le respect du principe d'ouverture/fermeture…
La règle pour ne pas autoriser la dépendance circulaire est de forcer une structure claire des paquets.


(Alternative février 2013, concernant src uniquement)
Vous pouvez trouver la disposition classique illustrée dans " Code Layout GitHub ":

L'application et les deux bibliothèques résident sur Github, chacune dans son propre référentiel.
$GOPATH Est la racine du projet - chacun de vos dépôts Github sera extrait de plusieurs dossiers sous $GOPATH.

Votre disposition de code ressemblerait à ceci:

$GOPATH/
    src/
        github.com/
            jmcvetta/
                useless/
                    .git/
                    useless.go
                    useless_test.go
                    README.md
                uselessd/
                    .git/
                    uselessd.go
                    uselessd_test.go
                    README.md

Chaque dossier situé sous src/github.com/jmcvetta/ Est la racine d'un contrôle séparé de git.

Cela a cependant suscité quelques critiques, dans ce page reddit :

Je recommande fortement de ne pas structurer le rapport comme vous l'avez fait, cela cassera "go get", Ce qui est l'une des choses les plus utiles sur Go.
Il est de loin préférable d'écrire votre code pour les personnes qui connaissent Go, car ce sont probablement elles qui le compilent.
Et pour ceux qui ne le font pas, ils auront au moins une idée de la langue.

Placez le package principal à la racine du référentiel.
Placez les actifs dans un sous-répertoire (pour que les choses restent ordonnées).
Conservez le contenu du code dans un sous-paquet (au cas où quelqu'un voudrait le réutiliser en dehors de votre binaire).
Ajoutez un script de configuration à la racine du référentiel pour faciliter la recherche.

Le téléchargement, la construction, l’installation et la configuration ne sont que deux étapes:

  • "go get <your repo path>": Télécharge et installe le code aller, avec un sous-répertoire pour les actifs
  • $GOPATH/<your repo path>/setup.sh: Distribue les actifs au bon endroit et installe le service
123
VonC

Je suppose que par "projet", vous ne voulez pas dire un paquet Go, mais un logiciel que vous développez. Sinon, vous pouvez obtenir de l'aide ici et ici . Toutefois, ce n'est pas si différent de l'écriture de packages pour Go: utilisez des packages, créez un dossier pour chaque package et combinez ces packages dans votre application.

Pour vous faire une opinion, vous pouvez regarder les dépôts de tendances sur Go sur github: https://github.com/trending/go . Des exemples notables sont cayley et zeus .

Le schéma le plus populaire consiste probablement à avoir un fichier principal Go et de nombreux modules et sous-modules dans leurs propres répertoires. Si vous avez plusieurs méta-fichiers (doc, licence, modèles, ...), vous voudrez peut-être placer le code source dans un sous-répertoire. C'est ce que j'ai fait jusqu'à présent.

7
nemo

Vous devriez probablement aussi jeter un coup d'œil sur ce dépôt. Il montre beaucoup d’idées sur la structure des applications: https://github.com/golang-standards/project-layout

1
Tarion

Il existe une approche recommandée de la part des auteurs de Golang qui définit comment mettre en forme votre code de manière à fonctionner au mieux avec les outils go et à prendre en charge les systèmes de contrôle de source.

1
FigmentEngine