5.4 KiB
Go项目(project)一般有两类:library和executable。library是以构建库为目的的Go项目,而executable则是以构建二进制可执行文件为目的的Go项目。
- library对应上图的package
- executable对应上图的command
1.1 basic package 基本库
project-root-directory/
├── go.mod
├── modname.go
└── modname_test.go
或
project-root-directory/
├── go.mod
├── modname.go
├── modname_test.go
├── auth.go
├── auth_test.go
├── hash.go
└── hash_test.go
你的代码要依赖该module,直接通过下面import语句便可以将该module导入:
import "github.com/someuser/modname"
1.2 package with supporting packages 库库调用
稍复杂或规模稍大的一些package类项目,会将很多功能分拆到supporting packages中,并且通常项目作者是不希望导出这些supporting packages的,这样这些supporting packages便可以不作为暴露的API的一部分,后续重构和优化起来十分方便,对package的用户也是无感的。这样Go官方建议将这些supporting packages放入internal目录
project-root-directory/
├── go.mod
├── modname.go
├── modname_test.go
└── internal/
├── auth/
│ ├── auth.go
│ └── auth_test.go
└── hash/
├── hash.go
└── hash_test.go
modname.go或modname_test.go可以通过下面导入语句使用internal下面的包:
import "github.com/someuser/modname/internal/auth"
1.3 multiple packages 多库
作为一个库项目,作者可能要暴露不止一个package,可能是多个packages。这不会给Go项目目录布局带来过多复杂性,我们只需多建立几个导出package的目录就ok了。下面是一个multiple packages的示例:
project-root-directory/
├── go.mod
├── modname.go
├── modname_test.go
├── auth/
│ ├── auth.go
│ ├── auth_test.go
│ └── token/
│ ├── token.go
│ └── token_test.go
├── hash/
│ ├── hash.go
│ └── hash_test.go
└── internal/
└── trace/
├── trace.go
└── trace_test.go
我们看到这个示例在repo(以托管在http://github.com/user/modname下为例)顶层放置了多个导出包:
github.com/user/modname
github.com/user/modname/auth
github.com/user/modname/hash
并且顶层的auth目录下还有一个二级的导出包token,其导入路径为:
github.com/user/modname/auth/token
2.1 basic command 基本项目
project-root-directory/
├── go.mod
└── main.go
或
project-root-directory/
├── go.mod
├── main.go
├── auth.go
├── auth_test.go
├── hash.go
└── hash_test.go
从示例我们可以看到,basic command类项目的repo下面只可构建出一个可执行文件,main函数放在main.go中,其他源文件也在repo根目录下,并同样放在main包中。
2.2 command with supporting packages 项目调库
project-root-directory/
├── go.mod
├── main.go
└── internal/
├── auth/
│ ├── auth.go
│ └── auth_test.go
└── hash/
├── hash.go
└── hash_test.go
和package with supporting packages不同的是,main.go使用的包名为main,这样Go编译器才能将其构建为command。
2.3 multiple commands 多项目
project-root-directory/
├── go.mod
├── prog1/
│ └── main.go
├── prog2/
│ └── main.go
└── internal/
└── trace/
├── trace.go
└── trace_test.go
这个示例将每个command放置在一个单独的目录下(比如prog1、prog2等),supporting packages和之前的建议一样,统一放到internal下面。这样我们可以通过下面步骤来编译command:
$go build github.com/someuser/modname/prog1
$go build github.com/someuser/modname/prog2
command的用户通过下面步骤可以安装这些命令
$go install github.com/someuser/modname/prog1@latest
$go install github.com/someuser/modname/prog2@latest
3.1 packages and commands 库与项目混合
在同一个项目下面,既有多个可导出的packages,又有多个commands。下面是一个此类复杂项目的示例
project-root-directory/
├── go.mod
├── modname.go
├── modname_test.go
├── auth/
│ ├── auth.go
│ ├── auth_test.go
│ └── token/
│ ├── token.go
│ └── token_test.go
├── hash/
│ ├── hash.go
│ └── hash_test.go
├── internal/
│ └── trace/
│ ├── trace.go
│ └── trace_test.go
└── cmd/
├── prog1/
│ └── main.go
└── prog2/
└── main.go
为了区分导出package和command,这个示例增加了一个专门用来存放command的cmd目录,prog1和prog2两个command都放在这个目录下。这也是Go语言的一个惯例
可以参考GitHub - go-nunu/nunu: A CLI tool for building Go applications. 项目