Go Project Layout 总结

原创
2019/02/14 14:53
阅读数 3.1K

背景

Go 没有对项目的 layout 有硬性规定,也没有官方版本的 best practice,所以社区内部有几种不同的实践方式,可根据自身需求自行参考。本文仅作简要总结

参考方案

根据社区 Standard Go Project Layout 提出的方案,我们可以将一个 Go Project 划分成以下几大目录:

 

Go Directories

/cmd

Main applications for this project.

The directory name for each application should match the name of the executable you want to have (e.g., /cmd/myapp).

Don't put a lot of code in the application directory. If you think the code can be imported and used in other projects, then it should live in the /pkg directory. If the code is not reusable or if you don't want others to reuse it, put that code in the /internal directory. You'll be surprised what others will do, so be explicit about your intentions!

It's common to have a small main function that imports and invokes the code from the /internal and /pkg directories and nothing else.

/internal

Private application and library code. This is the code you don't want others importing in their applications or libraries.

Put your actual application code in the /internal/app directory (e.g., /internal/app/myapp) and the code shared by those apps in the /internal/pkg directory (e.g., /internal/pkg/myprivlib).

/pkg

Library code that's ok to use by external applications (e.g., /pkg/mypubliclib). Other projects will import these libraries expecting them to work, so think twice before you put something here :-)

It's also a way to group Go code in one place when your root directory contains lots of non-Go components and directories making it easier to run various Go tools (as mentioned in the Best Practices for Industrial Programming from GopherCon EU 2018).

See the /pkg directory if you want to see which popular Go repos use this project layout pattern. This is a common layout pattern, but it's not universally accepted and some in the Go community don't recommend it.

/vendor

Application dependencies (managed manually or by your favorite dependency management tool like dep).

Don't commit your application dependencies if you are building a library.

Service Application Directories

/api

OpenAPI/Swagger specs, JSON schema files, protocol definition files.

Web Application Directories

/web

Web application specific components: static web assets, server side templates and SPAs.

Common Application Directories

/configs

Configuration file templates or default configs.

Put your confd or consul-template template files here.

/init

System init (systemd, upstart, sysv) and process manager/supervisor (runit, supervisord) configs.

/scripts

Scripts to perform various build, install, analysis, etc operations.

These scripts keep the root level Makefile small and simple (e.g., https://github.com/hashicorp/terraform/blob/master/Makefile).

/build

Packaging and Continuous Integration.

Put your cloud (AMI), container (Docker), OS (deb, rpm, pkg) package configurations and scripts in the /build/package directory.

Put your CI (travis, circle, drone) configurations and scripts in the /build/ci directory. Note that some of the CI tools (e.g., Travis CI) are very picky about the location of their config files. Try putting the config files in the /build/ci directory linking them to the location where the CI tools expect them (when possible).

/deployments

IaaS, PaaS, system and container orchestration deployment configurations and templates (docker-compose, kubernetes/helm, mesos, terraform, bosh).

/test

Additional external test apps and test data. Feel free to structure the /test directory anyway you want. For bigger projects it makes sense to have a data subdirectory. For example, you can have /test/data or /test/testdata if you need Go to ignore what's in that directory. Note that Go will also ignore directories or files that begin with "." or "_", so you have more flexibility in terms of how you name your test data directory.

Other Directories

/docs

Design and user documents (in addition to your godoc generated documentation).

/tools

Supporting tools for this project. Note that these tools can import code from the /pkg and /internal directories.

/examples

Examples for your applications and/or public libraries.

/third_party

External helper tools, forked code and other 3rd party utilities (e.g., Swagger UI).

/githooks

Git hooks.

/assets

Other assets to go along with your repository (images, logos, etc).

/website

This is the place to put your project's website data if you are not using Github pages.

Directories You Shouldn't Have

/src

Some Go projects do have a src folder, but it usually happens when the devs came from the Java world where it's a common pattern. If you can help yourself try not to adopt this Java pattern. You really don't want your Go code or Go projects to look like Java :-)

Don't confuse the project level /src directory with the /src directory Go uses for its workspaces as described in How to Write Go Code. The $GOPATH environment variable points to your (current) workspace (by default it points to $HOME/go on non-windows systems). This workspace includes the top level /pkg, /bin and /src directories. Your actual project ends up being a sub-directory under /src, so if you have the /src directory in your project the project path will look like this: /some/path/to/workspace/src/your_project/src/your_code.go. Note that with Go 1.11 it's possible to have your project outside of your GOPATH, but it still doesn't mean it's a good idea to use this layout pattern.

 

要区分和注意的地方

和 golang 的 workspace 的区别

golnag 的workspace 使用 GOPATH 环境变量设置,请参考 这篇文章 ,详细说明了 GOPATH 的设置方式,$GOPATH 目录下约定有三个子目录:src,bin,pkg,在src 目录下建立我们的项目,项目的路径为 :

  • $GOPATH/src/github.com/your_github_username/your_project:绝对路径,推荐使用;

  • $GOPATH/src/your_project:相对路径,可以用,但不推荐

而在 your_project 下的目录结构就是我们上图所说的目录结构。

注意,src 目录下可以建立多个项目

 

总结

就目前而言,Go 对于工程项目的 layout 并未有官方权威的指导(区别于 Go Workspace 的 layout,Go 为此有着明确的约束,即要有 bin/pkg/ 和 src/),但是开源社区中的大部分 Go 项目对一些目录的划分已经有了一些默契。可参考的有 KuberntesPromethusetcd 等等。对于应用项目(即总是可编译出一个可执行文件的项目),一般都会有 cmd/pkg/ 和 vendor/,其他一些目录则根据社区习惯会有所不同。对于非应用项目,比如一些库,则上述的 layout 设计并不能完全适用,且从目前社区的编码习惯来看,不少库项目的 layout 都相对比较自由(比如很多项目就直接将其所有代码放置于项目根目录下)。

从团队协作的角度来看,必须对 Go 工程项目的 layout 定义出一个最小通用子集并为此达成使用默契

所以,当你开始一个 Go 项目的时候,你可以这么做:

  • 确定你要写的项目是 application 还是 library,如果是 application,尽可能有 cmd/pkg/ 和 vendor/ 目录;如果是 library,可参考上述规则;

  • 如果是一个很小的项目,可以不需要所谓的目录设计,尽可能保持清晰简单即可;

  • 参考设计不构成硬性的约束条件,一切都要以实际项目的需求来权衡设计,但最终还是要能保证清晰简单;

参考:https://zhengyinyong.com/go-project-layout-design.html

=======END=======

展开阅读全文
Go
打赏
0
3 收藏
分享
加载中
更多评论
打赏
0 评论
3 收藏
0
分享
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部