Organizando um projeto Go de vários arquivos [fechado]

238

Nota: esta pergunta está relacionada a esta , mas dois anos são muito longos na história do Go.

Qual é a maneira padrão de organizar um projeto Go durante o desenvolvimento?

Meu projeto é um pacote único mypack, então acho que coloquei todos os arquivos .go em um mypackdiretório.

Mas então, eu gostaria de testá-lo durante o desenvolvimento, para que eu precise de pelo menos um arquivo que declare o mainpacote, para que eu possa fazergo run trypack.go

Como devo organizar isso? Preciso fazer isso go install mypacktoda vez que quiser experimentar?

Blacksad
fonte
14
Este breve screencast é incrível: youtube.com/watch?v=XCsL89YtqCs
Matt:
Este é outro link útil para entender como organizar um projeto com pacotes. Mais fácil de seguir do que o código oficial How to Write go, eu acho.
IamNaN 9/04
Para o novo sistema de módulos Go, esta resposta abrange a estrutura do módulo, organizando os pacotes dentro de um módulo, se há ou não vários módulos em um repositório único etc. Eventualmente, o documento de introdução oficial "Como escrever código Go" será atualizado para módulos , mas isso ainda não aconteceu. (Se você é iniciante no Go e novo no Go, ainda vale a pena ler o documento "Como escrever o código Go" antes de ler mais sobre os módulos, pois grande parte da documentação dos módulos pressupõe familiaridade com o GOPATH).
typical182

Respostas:

171

Eu recomendaria revisar esta página em Como escrever código Go

Ele documenta como estruturar seu projeto de go buildmaneira amigável e também como escrever testes. Os testes não precisam ser um cmd usando o mainpacote. Eles podem simplesmente ser funções nomeadas do TestX como parte de cada pacote e depois as go testdescobrirão.

A estrutura sugerida nesse link na sua pergunta está um pouco desatualizada, agora com o lançamento do Go 1. Você não precisa mais colocar um pkgdiretório src. Os únicos 3 diretórios relacionados a especificações são os 3 na raiz do seu GOPATH: bin, pkg, src. Abaixo do src, você pode simplesmente colocar o seu projeto mypacke, por baixo, todos os seus arquivos .go, incluindo o mypack_test.go

go build irá então construir no nível raiz pkg e bin.

Portanto, seu GOPATH pode ficar assim:

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

export GOPATH=$HOME/projects

$ go build mypack
$ go test mypack

Atualização: a partir de> = Ir 1.11, o sistema Module é agora uma parte padrão do ferramental e o conceito GOPATH está quase se tornando obsoleto.

jdi
fonte
26
Use $ HOME em vez de ~ ao exportar variáveis.
Johan S
6
Por que $ HOME é recomendado sobre ~ ao exportar variáveis?
425nesp
8
Porque ~ não é uma variável, apenas um alias.
Pih
6
@ 425nesp Johan está enganado - não está. Os shells variam, mas o bash se expande ~ao definir variáveis ​​ambientais , assim como o busybox bourne shell, por exemplo. Tente você mesmo: export BOB=~ && env | grep ^BOBvai renderBOB=/your/homedir
Austin Adams
1
$HOMEtrabalha em mais conchas ~, por exemplo, emfish
hoijui 23/03/19
60

jdi tem as informações corretas sobre o uso de GOPATH. Eu acrescentaria que, se você pretende ter um binário, também poderá adicionar um nível adicional aos diretórios.

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

running go build myproj/mypackirá construir o mypackpacote junto com suas dependências running go build myproj/myappirá construir o myappbinário junto com suas dependências que provavelmente incluem a mypackbiblioteca.

Jeremy Wall
fonte
Isso faria sentido, é claro, se ele realmente tivesse um cmd principal. Parecia que ele estava apenas criando um pacote de biblioteca.
JDI
50

Estudei vários projetos Go e há uma boa variação. Você pode dizer quem vem de C e quem vem de Java, pois o primeiro despeja quase tudo no diretório raiz do projeto em um mainpacote e o último tende a colocar tudo em um srcdiretório. Nem é ideal, no entanto. Cada um tem consequências porque afeta os caminhos de importação e como os outros podem reutilizá-los.

Para obter os melhores resultados, elaborei a seguinte abordagem.

myproj/
  main/
    mypack.go
  mypack.go

Onde mypack.goestá package mypacke main/mypack.goestá (obviamente) package main.

Se você precisar de arquivos de suporte adicionais, terá duas opções. Mantenha todos eles no diretório raiz ou coloque os arquivos de suporte privado em um libsubdiretório. Por exemplo

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

Coloque os arquivos em um libdiretório apenas se eles não forem importados por outro projeto. Em outras palavras, se eles são arquivos de suporte particulares . Essa é a idéia por trás de ter lib- para separar interfaces públicas de privadas.

Fazer as coisas dessa maneira fornecerá um bom caminho de importação myproj.org/mypackpara reutilizar o código em outros projetos. Se você usar lib, os arquivos de suporte interno terão um caminho de importação indicativo disso myproj.org/lib/mysupport,.

Ao construir o projeto, use main/mypack, por exemplo go build main/mypack. Se você tiver mais de um executável, também poderá separá-los mainsem precisar criar projetos separados. por exemplo, main/myfoo/myfoo.goe main/mybar/mybar.go.

trans
fonte
14
Idomatic é usar um cmd/nameOfMyExecutablesubdiretório para o pacote principal (só é necessário cmd/…se você tiver vários comandos; veja golang.org/x/tools/cmd; caso contrário, é comum trocá-lo e utilizá - lo main.gono nível superior). A maneira como você o go installcriará um executável "main" (ou "main.exe"). Além disso, o idiomático é usar um internalsubdiretório para um subconjunto interno ao pacote / programa que não deve ser usado em outros lugares (espera-se que as versões futuras do Go impeçam ninguém mais importar internalpacotes feitos dessa maneira).
Dave C
21

Acho muito útil entender como organizar o código em Golang neste capítulo http://www.golang-book.com/11 do livro escrito por Caleb Doxsey

edap
fonte
13

Não parece haver uma maneira padrão de organizar projetos Go, mas https://golang.org/doc/code.html especifica uma prática recomendada para a maioria dos projetos. A resposta do jdi é boa, mas se você usa o github ou o bitbucket e também possui bibliotecas adicionais, deve criar a seguinte estrutura:

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

Fazendo dessa maneira, você pode ter um repositório separado para mylib que pode ser usado para outros projetos e pode ser recuperado por "vá buscar". Seu projeto mypack pode importar sua biblioteca usando "github.com/username/mylib". Para maiores informações:

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

alexdotc
fonte
6

Mantenha os arquivos no mesmo diretório e use package mainem todos os arquivos.

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

Então corra:

~/myproj/your-program$ go build && ./your-program
Gustav
fonte
1
Como isso pode funcionar? Seu main.go precisa ser package main; presumivelmente o lib.go está em um pacote diferente, então a ferramenta go reclama que você não pode ter dois pacotes em uma única pasta.
precisa saber é o seguinte
1
Muito OP pede como dividir um pacote, o programa principal, em muitos arquivos. O lib.go está no mesmo pacote neste caso.
Gustav
Ah, obrigado pelo esclarecimento.
precisa saber é o seguinte
@Gustav, tenho a mesma pergunta. Parece que se eu colocar o pacote main no lib.go, no main.go, não posso chamar funções definidas no lib.go.
Qian Chen
@ElgsQianChen Os métodos precisam ser públicos, precisam começar com uma letra maiúscula. Por exemplo, MyMethod () ou MyStruct {...}.
Gustav
6

Vamos explorar como o go get repository_remote_urlcomando gerencia a estrutura do projeto $GOPATH. Se fizermos um, go get github.com/gohugoio/hugoele clonará o repositório em

$ GOPATH / src / repository_remote / user_name / project_name


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

Essa é uma boa maneira de criar o caminho do projeto inicial . Agora vamos explorar quais são os tipos de projeto e como suas estruturas internas são organizadas. Todos os projetos golang na comunidade podem ser classificados em

  • Libraries (sem binários executáveis)
  • Single Project (contém apenas 1 binário executável)
  • Tooling Projects (contém vários binários executáveis)

Geralmente, os arquivos do projeto golang podem ser empacotados sob quaisquer princípios de design , como DDD , POD

A maioria dos projetos disponíveis segue este Design Orientado a Pacotes

O Design Orientado a Pacotes incentiva o desenvolvedor a manter a implementação apenas dentro de seus próprios pacotes, além do /internalpacote que esses pacotes não podem se comunicar.


Bibliotecas

  • Projetos como drivers de banco de dados , qt podem ser colocados nessa categoria.
  • Algumas bibliotecas, como cores , agora seguem uma estrutura plana sem outros pacotes.
  • A maioria desses projetos de biblioteca gerencia um pacote chamado interno .
  • /internal O pacote é usado principalmente para ocultar a implementação de outros projetos.
  • Não possui binários executáveis; portanto, não há arquivos que contenham a função principal .

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

Projeto único

  • Projetos como hugo , etcd têm uma única função principal no nível raiz e.
  • O objetivo é gerar um único binário

Projetos de Ferramentas

  • Projetos como kubernetes , go-ethereum têm várias funções principais organizadas sob um pacote chamado cmd
  • cmd/ O pacote gerencia o número de binários (ferramentas) que queremos construir

 ~/$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
fonte