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.

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 基本库

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. 项目