|
|
|
|
![[Pasted image 20231201224140.png]]
|
|
|
|
|
|
|
|
|
|
Go项目(project)一般有两类:library和executable。library是以构建库为目的的Go项目,而executable则是以构建二进制可执行文件为目的的Go项目。
|
|
|
|
|
+ library对应上图的package
|
|
|
|
|
+ executable对应上图的command
|
|
|
|
|
|
|
|
|
|
## 1.1 basic package 基本库
|
|
|
|
|
```text
|
|
|
|
|
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导入:
|
|
|
|
|
```text
|
|
|
|
|
import "github.com/someuser/modname"
|
|
|
|
|
```
|
|
|
|
|
## 1.2 package with supporting packages 库库调用
|
|
|
|
|
稍复杂或规模稍大的一些package类项目,会将很多功能分拆到supporting packages中,并且通常项目作者是不希望导出这些supporting packages的,这样这些supporting packages便可以不作为暴露的API的一部分,后续重构和优化起来十分方便,对package的用户也是无感的。这样Go官方建议将这些supporting packages放入[internal目录](https://link.zhihu.com/?target=https%3A//tonybai.com/2015/07/10/some-changes-in-go-1-5/)
|
|
|
|
|
```text
|
|
|
|
|
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下面的包:
|
|
|
|
|
```text
|
|
|
|
|
import "github.com/someuser/modname/internal/auth"
|
|
|
|
|
```
|
|
|
|
|
## 1.3 multiple packages 多库
|
|
|
|
|
作为一个库项目,作者可能要暴露不止一个package,可能是多个packages。这不会给Go项目目录布局带来过多复杂性,我们只需多建立几个导出package的目录就ok了。下面是一个multiple packages的示例:
|
|
|
|
|
```text
|
|
|
|
|
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](https://link.zhihu.com/?target=http%3A//github.com/user/modname)下为例)顶层放置了多个导出包:
|
|
|
|
|
```text
|
|
|
|
|
github.com/user/modname
|
|
|
|
|
github.com/user/modname/auth
|
|
|
|
|
github.com/user/modname/hash
|
|
|
|
|
```
|
|
|
|
|
并且顶层的auth目录下还有一个二级的导出包token,其导入路径为:
|
|
|
|
|
```text
|
|
|
|
|
github.com/user/modname/auth/token
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 2.1 basic command 基本项目
|
|
|
|
|
```text
|
|
|
|
|
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 项目调库
|
|
|
|
|
```text
|
|
|
|
|
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 多项目
|
|
|
|
|
```text
|
|
|
|
|
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:
|
|
|
|
|
```text
|
|
|
|
|
$go build github.com/someuser/modname/prog1
|
|
|
|
|
$go build github.com/someuser/modname/prog2
|
|
|
|
|
```
|
|
|
|
|
command的用户通过下面步骤可以安装这些命令
|
|
|
|
|
```text
|
|
|
|
|
$go install github.com/someuser/modname/prog1@latest
|
|
|
|
|
$go install github.com/someuser/modname/prog2@latest
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 3.1 packages and commands 库与项目混合
|
|
|
|
|
在同一个项目下面,既有多个可导出的packages,又有多个commands。下面是一个此类复杂项目的示例
|
|
|
|
|
```text
|
|
|
|
|
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.](https://github.com/go-nunu/nunu/tree/main) 项目
|