You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
5.4 KiB

2 years ago
![[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) 项目