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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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