Visão geral
Este é um layout básico para projetos de aplicações em Go. Não é um padrão oficial definido pela equipe de desenvolvimento principal do Go; no entanto, é um conjunto de padrões de layout de projetos históricos e emergentes comuns no ecossistema Go. Alguns desses padrões são mais populares do que outros. Ele também possui uma série de pequenos aprimoramentos junto com vários diretórios de suporte comuns a qualquer aplicativo grande o suficiente do mundo real.
Se você está tentando aprender Go, se está construindo um PoC(Prova de conceito) ou um pequeno projeto pessoal para você, este layout de projeto é um exagero. Comece com algo realmente simples (um único arquivo main.go
é mais do que suficiente). Conforme seu projeto cresce, lembre-se de que será importante garantir que seu código esteja bem estruturado, caso contrário, você acabará com um código confuso com muitas dependências ocultas e estados globais. Quando você tiver mais pessoas trabalhando no projeto, precisará de ainda mais estrutura. É quando é importante apresentar uma maneira comum de gerenciar pacotes/bibliotecas. Quando você tem um projeto de código aberto ou quando conhece outros projetos, importe o código do seu repositório de projetos, é quando é importante ter pacotes e códigos privados (também conhecidos como internal
). Clone o repositório, mantenha o que você precisa e exclua todo o resto! Só porque está lá, não significa que você precise usar tudo. Nenhum desses padrões é usado em todos os projetos. Mesmo o padrão vendor
não é universal.
Com Go 1.14 Go Modules
estão finalmente prontos para produção. Use Go Modules
a menos que você tenha um motivo específico para não usá-los e, se tiver, não precisa se preocupar com $GOPATH e onde você colocou seu projeto. O arquivo go.mod
básico no reposiório assume que seu projeto está hospedado no GitHub, mas não é um requisito. O caminho do módulo pode ser qualquer coisa, embora o primeiro componente do caminho do módulo deva ter um ponto em seu nome (a versão atual do Go não o impõe mais, mas se você estiver usando versões um pouco mais antigas, não se surpreenda se suas compilações falharem sem isto). Veja as issues 37554
e 32819
se você quiser saber mais sobre isso.
Este layout de projeto é intencionalmente genérico e não tenta impor uma estrutura de pacote Go específica.
Este é um esforço da comunidade. Abra uma nova issue se você ver um novo padrão ou se você acha que um dos padrões existentes precisa ser atualizado.
Se precisar de ajuda com nomenclatura, formatação e estilo, comece executando gofmt
e golint
. Além disso, certifique-se de ler estas diretrizes e recomendações de estilo de código Go:
- https://talks.golang.org/2014/names.slide
- https://golang.org/doc/effective_go.html#names
- https://blog.golang.org/package-names
- https://github.com/golang/go/wiki/CodeReviewComments
- Style guideline for Go packages (rakyll/JBD)
Veja Go Project Layout
para obter informações adicionais.
Mais sobre como nomear e organizar pacotes, bem como outras recomendações de estrutura de código:
- GopherCon EU 2018: Peter Bourgon - Best Practices for Industrial Programming
- GopherCon Russia 2018: Ashley McNamara + Brian Ketelsen - Go best practices.
- GopherCon 2017: Edward Muller - Go Anti-Patterns
- GopherCon 2018: Kat Zien - How Do You Structure Your Go Apps
Uma postagem chinesa sobre as diretrizes de design orientado a pacotes e a camada de arquitetura
Diretórios Go
/cmd
Principais aplicações para este projeto.
O nome do diretório para cada aplicação deve corresponder ao nome do executável que você deseja ter (ex. /cmd/myapp
).
Não coloque muitos códigos no diretório da aplicação. Se você acha que o código pode ser importado e usado em outros projetos, ele deve estar no diretório /pkg
. Se o código não for reutilizável ou se você não quiser que outros o reutilizem, coloque esse código no diretório /internal
. Você ficará surpreso com o que os outros farão, então seja explícito sobre suas intenções!
É comum ter uma pequena função main
que importa e invoca o código dos diretórios /internal
e /pkg
e nada mais.
Veja o diretório /cmd
para mais exemplos.
/internal
Aplicação privada e código de bibliotecas. Este é o código que você não quer que outras pessoas importem em suas aplicações ou bibliotecas. Observe que esse padrão de layout é imposto pelo próprio compilador Go. Veja o Go 1.4 release notes
para mais detalhes. Observe que você não está limitado ao diretório internal
de nível superior. Você pode ter mais de um diretório internal
em qualquer nível da árvore do seu projeto.
Opcionalmente, você pode adicionar um pouco de estrutura extra aos seus pacotes internos para separar o seu código interno compartilhado e não compartilhado. Não é obrigatório (especialmente para projetos menores), mas é bom ter dicas visuais que mostram o uso pretendido do pacote. Seu atual código da aplicação pode ir para o diretório /internal/app
(ex. /internal/app/myapp
) e o código compartilhado por essas aplicações no diretório /internal/pkg
(ex. /internal/pkg/myprivlib
).
/pkg
Código de bibliotecas que podem ser usados por aplicativos externos (ex. /pkg/mypubliclib
). Outros projetos irão importar essas bibliotecas esperando que funcionem, então pense duas vezes antes de colocar algo aqui :-) Observe que o diretório internal
é a melhor maneira de garantir que seus pacotes privados não sejam importáveis porque é imposto pelo Go. O diretório /pkg
contudo é uma boa maneira de comunicar explicitamente que o código naquele diretório é seguro para uso. I'll take pkg over internal
A postagem no blog de Travis Jeffery fornece uma boa visão geral dos diretórios pkg
e internal
, e quando pode fazer sentido usá-los.
É também uma forma de agrupar o código Go em um só lugar quando o diretório raiz contém muitos componentes e diretórios não Go, tornando mais fácil executar várias ferramentas Go (conforme mencionado nestas palestras: Best Practices for Industrial Programming
da GopherCon EU 2018, GopherCon 2018: Kat Zien - How Do You Structure Your Go Apps e GoLab 2018 - Massimiliano Pippi - Project layout patterns in Go).
Consulte o diretório /pkg
se quiser ver quais repositórios Go populares usam esse padrão de layout de projeto. Este é um padrão de layout comum, mas não é universalmente aceito e alguns na comunidade Go não o recomendam.
Não há problema em não usá-lo se o projeto do seu aplicativo for muito pequeno e onde um nível extra de aninhamento não agrega muito valor (a menos que você realmente queira :-)). Pense nisso quando estiver ficando grande o suficiente e seu diretório raiz ficar muito ocupado (especialmente se você tiver muitos componentes de aplicativos não Go).
/vendor
Dependências de aplicativos (gerenciadas manualmente ou por sua ferramenta de gerenciamento de dependências favorita, como o novo recurso integrado Go Modules
). O comando go mod vendor
criará o diretório /vendor
para você. Note que você pode precisar adicionar a flag -mod=vendor
ao seu comando go build
se você não estiver usando Go 1.14 onde ele está ativado por padrão.
Não comprometa as dependências do seu aplicativo se você estiver construindo uma biblioteca.
Observe que desde o Go 1.13
também habilitou o recurso de proxy do módulo (usando https://proxy.golang.org
como servidor proxy de módulo por padrão). Leia mais sobre isso aqui
para ver se ele se encaixa em todos os seus requisitos e restrições. Se isso acontecer, então você não precisará do diretório vendor
.
Diretórios de aplicativos de serviço
/api
Especificações OpenAPI/Swagger, arquivos de esquema JSON, arquivos de definição de protocolo.
Veja o diretório /api
para mais exemplos.
Diretórios de aplicativos da web
/web
Componentes específicos de aplicativos da Web: ativos estáticos da Web, modelos do lado do servidor e SPAs.
Diretórios de aplicativos comuns
/configs
Modelos de arquivo de configuração ou configurações padrão.
Coloque seus arquivos de modelo confd
ou consul-template
aqui.
/init
Configurações de inicialização do sistema (systemd, upstart, sysv) e gerenciador/supervisor de processos (runit, supervisord).
/scripts
Scripts para executar várias operações de construção, instalação, análise, etc.
Esses scripts mantêm o Makefile de nível raiz pequeno e simples (ex. https://github.com/hashicorp/terraform/blob/main/Makefile
).
Veja o diretório /scripts
para mais exemplos.
/build
Empacotamento e integração contínua.
Coloque suas configurações de pacote e scripts em nuvem (AMI), contêiner (Docker), sistema operacional (deb, rpm, pkg) no diretório /build/package
.
Coloque suas configurações e scripts de CI (travis, circle, drone) no diretório /build/ci
. Observe que algumas das ferramentas de CI (por exemplo, Travis CI) são muito exigentes quanto à localização de seus arquivos de configuração. Tente colocar os arquivos de configuração no diretório /build/ci
vinculando-os ao local onde as ferramentas de CI os esperam (quando possível).
/deployments
IaaS, PaaS, configurações e modelos de implantação de orquestração de sistema e contêiner (docker-compose, kubernetes / helm, mesos, terraform, bosh). Observe que em alguns repositórios (especialmente em aplicativos implantados com kubernetes), esse diretório é denominado /deploy
.
/test
Aplicações de testes externos adicionais e dados de teste. Sinta-se à vontade para estruturar o diretório /test
da maneira que quiser. Para projetos maiores, faz sentido ter um subdiretório de dados. Por exemplo, você pode ter /test/data
ou /test/testdata
se precisar que o Go ignore o que está naquele diretório. Observe que o Go também irá ignorar diretórios ou arquivos que começam com "." ou "_", para que você tenha mais flexibilidade em termos de como nomear seu diretório de dados de teste.
Veja o diretório /test
para mais exemplos.
Outros diretórios
/docs
Documentos do projeto e do usuário (além da documentação gerada pelo godoc).
Veja o diretório /docs
para mais exemplos.
/tools
Ferramentas de suporte para este projeto. Observe que essas ferramentas podem importar código dos diretórios /pkg
e /internal
.
Veja o diretório /tools
para mais exemplos.
/examples
Exemplos para seus aplicativos e / ou bibliotecas públicas.
Veja o diretório /examples
para mais exemplos.
/third_party
Ferramentas auxiliares externas, código bifurcado e outros utilitários de terceiros (por exemplo, Swagger UI).
/githooks
Git hooks.
/assets
Outros recursos para acompanhar seu repositório (imagens, logotipos etc).
/website
Este é o lugar para colocar os dados do site do seu projeto se você não estiver usando as páginas do GitHub.
Veja o diretório /website
para mais exemplos.
Diretórios que você não deveria ter
/src
Alguns projetos Go têm uma pasta src
, mas normalmente acontece quando os devs vêm do mundo Java, onde é um padrão comum. Se você puder se ajudar, tente não adotar esse padrão Java. Você realmente não quer que seu código Go ou projetos Go se pareçam com Java :-)
Não confunda o diretório /src
do nível do projeto com o diretório /src
que Go usa para seus espaços de trabalho, conforme descrito em How to Write Go Code
. A variável de ambiente $GOPATH
aponta para sua área de trabalho(atual) (por padrão, ela aponta para $HOME/go
em sistemas não Windows). Este espaço de trabalho inclui os diretórios de nível superior /pkg
, /bin
e /src
. Seu projeto atual acaba sendo um subdiretório em / src
, então se você tiver o diretório /src
em seu projeto, o caminho do projeto será parecido com este: /algum/caminho/para/workspace/src/your_project/src/ your_code.go
. Observe que com Go 1.11 é possível ter seu projeto fora de seu GOPATH
, mas ainda não significa que é uma boa ideia usar este padrão de layout.
Distintivos
-
Go Report Card - Ele irá escanear seu código com
gofmt
,go vet
,gocyclo
,golint
,ineffassign
,license
emisspell
. Substituagithub.com/golang-standards/project-layout
com sua referência de projeto. -
GoDoc - Ele fornecerá uma versão online da documentação gerada pelo GoDoc. Mude o link para apontar para seu projeto. -
Pkg.go.dev - Pkg.go.dev é um novo destino para Go discovery e docs. Você pode criar um emblema usando o badge generation tool.
-
Release - Ele mostrará o número da versão mais recente do seu projeto. Altere o link do github para apontar para seu projeto.
Notas
Um modelo de projeto mais opinativo com configurações, scripts e código de amostra/reutilizáveis é um WIP.