Go项目的终极配置

汪明军_3145 · · 784 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

【译文】原文地址
说明:本文最初发表在martinheinz.dev


对我来说,开始一个新项目时最大的麻烦就是试图把项目配置的“完美”。我总是尝试使用最优的目录结构,这样一切都容易找到,以及导入工作也方便,设置所有的命令,这样就可以达到一键/一条命令完成所需操作,比如找到最好的工具、格式化、测试框架等。

这个列表还在增加,远没有达到我满意的配置...除了本文介绍的终极最优Glang配置。

说明:这个配置工作的这么好,部分原因基于已有项目,如项目1项目2

我的项目仓库地址:https://github.com/MartinHeinz/go-project-blueprint

目录结构

首先,让我们回顾下我们项目的目录结构。包含几个顶级文件和4个目录:

  • pkg-先从简单的开始-pkg是一个Go package包含唯一的全局版本字符串。它是根据提交hash计算出来替换实际版本的。
    *config-这是一个配置目录,包含必要的环境变量文件。任何文件类型都可能被使用,但我推荐使用yaml文件,其可读性好。
    *build-这个目录包含构建和测试应用程序的所有的shell脚本以及为代码分析工具所生产的报告。
    *cmd-存放源代码目录。按照惯例,源代码目录命名为cmd,里面包含一个根据项目名称命名的目录,在本文中是blueprint。接下来,在这个目录中包含一个main.go文件用来运行整个应用程序的,还有其他划分成模块的源文件。

备注:根据一些反馈,我发现很多人喜欢使用internal和pkg目录来存放源代码。我个人发现这没必要也有点多余,因此我把所有源文件都存放在cmd目录,然后每个模块都包含独立的目录。

除目录外,还有很多文件,我们将在以下各节中讨论这些文件。

Go Module可实现完美的依赖关系管理

Go项目使用多种依赖管理策略。但是,从1.11版开始,Go就有官方的依赖项管理解决方案。我们所有的依赖项都在go.mod文件中列出,该文件可以在根目录中找到。看起来可能是这样:

module github.com/MartinHeinz/go-project-blueprint

go 1.12

require (
    github.com/spf13/viper v1.4.0
    github.com/stretchr/testify v1.4.0
)

实际源代码和配置

下面终于讲源代码了。如前所述,源代码会划分成包,每个包都对应cmd中一子目录。每个子目录包含各自的源文件和测试文件,如下:

./cmd/
└── blueprint
    ├── apis <- Package
    │   ├── apis_test.go
    │   ├── user.go
    │   └── user_test.go
    ├── daos <- Package
    │   ├── user.go
    │   └── user_test.go
    ├── services <- Package
    │   ├── user.go
    │   └── user_test.go
    ├── config <- Package
    │       └── config.go
    └── main.go

以上目录结构有助于可读性和可维护性,因为代码被划分成合理的包,便于浏览。至于配置,在本项目中我使用 Viper,一个Go配置库,可以处理各种格式、命令行参数和环境变量等。

那么这里如何使用Viper呢?我们可以看下config包:

var Config appConfig

type appConfig struct {
    // Example Variable, which is loaded in LoadConfig function
    ConfigVar string
}

// LoadConfig loads config from files
func LoadConfig(configPaths ...string) error {
    v := viper.New()
    v.SetConfigName("example")  // <- name of config file
    v.SetConfigType("yaml")
    v.SetEnvPrefix("blueprint")
    v.AutomaticEnv()
    for _, path := range configPaths {
        v.AddConfigPath(path)  // <- // path to look for the config file in
    }
    if err := v.ReadInConfig(); err != nil {
        return fmt.Errorf("failed to read the configuration file: %s", err)
    }
    return v.Unmarshal(&Config)
}

该package只含一个文件。其中声明了一个struct存放所有的config变量以及一个LoadConfig函数,加载配置。该函数接收配置文件,在我们的项目中将使用config目录所在路径,包含yaml文件。然后我们怎么使用呢?我们先在main.go中执行:

if err := config.LoadConfig("./config"); err != nil {
    panic(fmt.Errorf("invalid application configuration: %s", err))
}

上面的代码一般在应用程序中,启动加载配置的作用。

简单快速的测试

介绍完源代码结构后,第二重要的事情就是质量测试了。为了能写出很多好的测试,需要配置下使写测试更简单。我们可以使用Makefile添加test目标,将搜集和执行cmd目录中所有的测试用例。这些测试用例也会缓存,只有存在变更才会再执行。这点很重要,因为如果测试太慢您将终止运行和维护它们。除了单元测试,make test也可以帮助维护代码质量,因为每次执行测试都会运行gofmt和go vet。go fmt会强制格式化代码而go vet根据启发式算法会发现任何可疑代码构造。示例输出:

foo@bar:~$ make test
Running tests:
ok      github.com/MartinHeinz/go-project-blueprint/cmd/blueprint   (cached)
?       github.com/MartinHeinz/go-project-blueprint/cmd/blueprint/config    [no test files]
?       github.com/MartinHeinz/go-project-blueprint/pkg [no test files]

Checking gofmt: FAIL - the following files need to be gofmt'ed:
    cmd/blueprint/main.go

Checking go vet: FAIL
# github.com/MartinHeinz/go-project-blueprint/cmd/blueprint
cmd/blueprint/main.go:19:7: assignment copies lock value to l: sync.Mutex

Makefile:157: recipe for target 'test' failed
make: *** [test] Error 1

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:汪明军_3145

查看原文:Go项目的终极配置

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

784 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传