Organiser un projet Go à fichiers multiples [fermé]

238

Remarque: cette question est liée à celle-ci , mais deux ans, c'est très long dans l'histoire de Go.

Quelle est la manière standard d'organiser un projet Go pendant le développement?

Mon projet est un package unique mypack, donc je suppose que je mets tous les fichiers .go dans un mypackrépertoire.

Mais ensuite, je voudrais le tester pendant le développement donc j'ai besoin d'au moins un fichier déclarant le mainpaquet, pour que je puisse fairego run trypack.go

Comment dois-je organiser cela? Dois-je faire go install mypackchaque fois que je veux l'essayer?

Blacksad
la source
14
Ce bref screencast est génial: youtube.com/watch?v=XCsL89YtqCs
Matt
Ceci est un autre lien utile pour comprendre comment organiser un projet avec des packages. Je pense que c'est plus facile à suivre que le code officiel Comment écrire?
IamNaN
Pour le nouveau système de modules Go, cette réponse couvre la structure des modules, l'organisation des packages dans un module, le fait d'avoir ou non plusieurs modules dans un référentiel unique, etc. Finalement, le document d'introduction officiel "Comment écrire du code Go" sera mis à jour pour les modules , mais cela ne s'est pas encore produit. (Si vous êtes nouveau sur Go et que vous êtes nouveau sur les modules Go, il vaut toujours la peine de lire ce document "Comment écrire du code Go" avant d'en savoir plus sur les modules étant donné qu'une grande partie de la documentation des modules suppose une bonne connaissance de GOPATH).
typique182

Réponses:

171

Je recommanderais de revoir cette page sur Comment écrire du code Go

Il explique à la fois comment structurer votre projet de manière go buildconviviale et comment écrire des tests. Les tests n'ont pas besoin d'être un cmd utilisant le mainpackage. Elles peuvent simplement être des fonctions nommées TestX dans le cadre de chaque package, puis go testles découvriront.

La structure suggérée dans ce lien dans votre question est un peu dépassée, maintenant avec la sortie de Go 1. Vous n'avez plus besoin de placer un pkgrépertoire sous src. Les 3 seuls répertoires liés aux spécifications sont les 3 à la racine de votre GOPATH: bin, pkg, src. Sous src, vous pouvez simplement placer votre projet mypack, et en dessous se trouvent tous vos fichiers .go, y compris mypack_test.go

go build sera ensuite intégré au paquet et au niveau racine.

Votre GOPATH pourrait donc ressembler à ceci:

~/projects/
    bin/
    pkg/
    src/
      mypack/
        foo.go
        bar.go
        mypack_test.go

export GOPATH=$HOME/projects

$ go build mypack
$ go test mypack

Mise à jour: à partir de> = Go 1.11, le système de modules est maintenant une partie standard de l'outillage et le concept GOPATH est sur le point de devenir obsolète.

jdi
la source
26
Utilisez $ HOME au lieu de ~ lors de l'exportation de variables.
Johan S
6
Pourquoi est-il recommandé de $ HOME sur ~ lors de l'exportation de variables?
425nesp
8
Parce que ~ n'est pas une variable, juste un alias.
Pih
6
@ 425nesp Johan se trompe - ce n'est pas le cas. Les shells varient, mais bash se développe ~lors de la définition des variables d'environnement , tout comme le shell busybox bourne, par exemple. Essayez-le vous-même: export BOB=~ && env | grep ^BOBcéderaBOB=/your/homedir
Austin Adams
1
$HOMEfonctionne alors dans plus de coques ~, par exemple àfish
hoijui
60

jdi a les bonnes informations concernant l'utilisation de GOPATH. J'ajouterais que si vous avez l'intention d'avoir également un binaire, vous voudrez peut-être ajouter un niveau supplémentaire aux répertoires.

~/projects/src/
    myproj/
        mypack/
            lib.go
            lib_test.go
            ...
        myapp/
            main.go

en cours d'exécution go build myproj/mypackva construire le mypackpaquet avec ses dépendances en cours d'exécution go build myproj/myappva construire le myappbinaire avec ses dépendances qui incluent probablement la mypackbibliothèque.

Jeremy Wall
la source
Cela aurait du sens, bien sûr, s'il avait réellement un cmd principal. On dirait qu'il est en train de créer un package de bibliothèque.
jdi
50

J'ai étudié un certain nombre de projets Go et il y a pas mal de variations. Vous pouvez en quelque sorte dire qui vient de C et qui vient de Java, car le premier vidage à peu près tout dans le répertoire racine des projets dans un mainpackage, et le dernier a tendance à tout mettre dans un srcrépertoire. Cependant, aucun n'est optimal. Chacun a des conséquences car il affecte les chemins d'importation et la manière dont les autres peuvent les réutiliser.

Pour obtenir les meilleurs résultats, j'ai élaboré l'approche suivante.

myproj/
  main/
    mypack.go
  mypack.go

mypack.goest package mypacket main/mypack.goest (évidemment) package main.

Si vous avez besoin de fichiers de support supplémentaires, vous avez deux choix. Soit les conserver tous dans le répertoire racine, soit placer les fichiers de support privés dans un libsous - répertoire. Par exemple

myproj/
  main/
    mypack.go
  myextras/
    someextra.go
  mypack.go
  mysupport.go

Ou

myproj.org/
  lib/
    mysupport.go
    myextras/
      someextra.go
  main/
    mypack.go
  mypage.go

Ne placez les fichiers dans un librépertoire que s'ils ne sont pas destinés à être importés par un autre projet. En d'autres termes, s'il s'agit de fichiers de support privés . C'est l'idée derrière avoir lib--pour séparer les interfaces publiques des interfaces privées.

Faire les choses de cette façon vous donnera un bon chemin d'importation, myproj.org/mypackpour réutiliser le code dans d'autres projets. Si vous utilisez libalors les fichiers de support internes auront un chemin d'importation qui indique que, myproj.org/lib/mysupport.

Lors de la construction du projet, utilisez main/mypack, par exemple go build main/mypack. Si vous avez plusieurs exécutables, vous pouvez également séparer ceux qui se trouvent sous mainsans avoir à créer des projets distincts. par exemple main/myfoo/myfoo.goet main/mybar/mybar.go.

trans
la source
14
Idomatic consiste à utiliser un cmd/nameOfMyExecutablesous-répertoire pour le package principal (uniquement nécessaire cmd/…si vous avez plusieurs commandes; voir golang.org/x/tools/cmd; sinon, il est courant de l'échanger et de l'avoir main.goau niveau supérieur). La façon dont vous l'avez go installcréera un exécutable "principal" (ou "main.exe"). De plus, idiomatique consiste à utiliser un internalsous-répertoire pour un sous-package interne au package / programme qui n'est pas destiné à être utilisé ailleurs (il est prévu que les futures versions de Go n'imposeront à personne d'importer des internalpackages de cette manière).
Dave C
21

Je trouve très utile de comprendre comment organiser le code dans Golang ce chapitre http://www.golang-book.com/11 du livre écrit par Caleb Doxsey

edap
la source
13

Il ne semble pas y avoir de méthode standard pour organiser les projets Go, mais https://golang.org/doc/code.html spécifie une meilleure pratique pour la plupart des projets. La réponse de jdi est bonne mais si vous utilisez github ou bitbucket et que vous avez également des bibliothèques supplémentaires, vous devez créer la structure suivante:

~/projects/
bin/
pkg/
src/
  github.com/
    username/
        mypack/
            foo.go
            bar.go
            mypack_test.go
        mylib/
            utillib.go
            utillib_test.go

De cette façon, vous pouvez avoir un référentiel séparé pour mylib qui peut être utilisé pour d'autres projets et peut être récupéré par "go get". Votre projet mypack peut importer votre bibliothèque en utilisant "github.com/username/mylib". Pour plus d'informations:

http://www.alexvictorchan.com/2014/11/06/go-project-structure/

alexdotc
la source
6

Gardez les fichiers dans le même répertoire et utilisez package main dans tous les fichiers.

myproj/
   your-program/
      main.go
      lib.go

Exécutez ensuite:

~/myproj/your-program$ go build && ./your-program
Gustav
la source
1
Comment cela peut-il fonctionner? Votre main.go doit être le paquet principal; vraisemblablement lib.go est dans un package différent, alors l'outil go se plaint que vous ne pouvez pas avoir deux packages dans un seul dossier.
I82Much
1
@ I82Much OP demande comment diviser un package, le programme principal, en plusieurs fichiers. lib.go est dans le même paquet dans ce cas.
Gustav
Ah merci pour la clarification.
I82Much
@ Gustav, j'ai la même question. Il semble que si je mets le package main dans lib.go, dans main.go, je ne peux pas appeler les fonctions définies dans lib.go.
Qian Chen
@ElgsQianChen Les méthodes doivent être publiques, elles doivent commencer par une majuscule. Par exemple MyMethod () ou MyStruct {...}.
Gustav
6

Explorons comment la go get repository_remote_urlcommande gère la structure du projet sous $GOPATH. Si nous faisons un, go get github.com/gohugoio/hugoil clonera le référentiel sous

$ GOPATH / src / repository_remote / user_name / project_name


$ GOPATH / src / github.com/gohugoio/hugo

C'est une bonne façon de créer votre chemin de projet initial . Explorons maintenant quels sont les types de projets et comment leurs structures internes sont organisées. Tous les projets de golang dans la communauté peuvent être classés sous

  • Libraries (pas de binaires exécutables)
  • Single Project (contient seulement 1 binaire exécutable)
  • Tooling Projects (contient plusieurs binaires exécutables)

En règle générale, les fichiers de projet golang peuvent être regroupés sous tous les principes de conception tels que DDD , POD

La plupart des projets go disponibles suivent cette conception orientée package

La conception orientée package encourage le développeur à ne conserver l'implémentation qu'à l'intérieur de ses propres packages, à l'exception du /internalpackage que ces packages ne peuvent pas communiquer entre eux.


Bibliothèques

  • Des projets tels que les pilotes de base de données , qt peuvent être classés dans cette catégorie.
  • Certaines bibliothèques, telles que la couleur , suivent désormais une structure plate sans aucun autre package.
  • La plupart de ces projets de bibliothèque gèrent un package appelé internal .
  • /internal Le package est principalement utilisé pour masquer l'implémentation des autres projets.
  • Ne pas avoir de binaires exécutables, donc pas de fichiers contenant la fonction principale .

 ~/$GOPATH/
    bin/
    pkg/
    src/
      repository_remote/
        user_name/
            project_name/
              internal/
              other_pkg/

Projet unique

  • Des projets tels que hugo , etcd ont une seule fonction principale au niveau racine et.
  • L'objectif est de générer un seul binaire

Projets d'outillage

  • Des projets tels que kubernetes , go-ethereum ont plusieurs fonctions principales organisées sous un package appelé cmd
  • cmd/ le package gère le nombre de binaires (outils) que nous voulons construire

 ~/$GOPATH/
    bin/
    pkg/
    src/
      repository_remote/
        user_name/
            project_name/
              cmd/
                binary_one/
                   main.go
                binary_two/
                   main.go
                binary_three/
                   main.go
              other_pkg/
noelyahan
la source