使用go generate将YAML配置文件内嵌到项目中

目录

很多命令行程序会使用到配置文件,本文首先介绍命令行程序使用配置文件的几种方式,然后介绍如何在 Go 程序中内置 YAML 配置文件。

使用配置文件的常见方式

命令行程序使用配置文件有如下几种方式:

固定目录

例如使用程序目录中的 config 目录,或者使用诸如 /etc 等系统目录。

环境变量

使用环境变量设置配置文件的目录。例如 ecCodes 使用 ECCOES_DEFINITION_PATH 设置 definition 目录。

命令行参数指定

更直接的方式就是在命令行参数中指定配置文件路径,这也是最容易实现的一种方式。

我常使用的方法

我个人编写的程序一般都采用命令行或环境变量方式。

每次执行命令都指定配置文件的路径十分不方便,对用户不友好。所以我一般对命令进行一定的封装,内置配置文件路径:

#!/usr/bin/env bash
export ECFLOW_CHECKER_CONFIG_PATH=/g11/wangdp/project/work/nost-go/ecflow-client-go/dist/conf
/g11/wangdp/project/work/nost-go/ecflow-client-go/bin/ecflow_checker $@

HPC 上普通用户没有管理员权限,无法使用固定的系统目录。 这种方式只能将配置目录指向某个用户目录,有一定的风险。 而且业务系统中不允许使用非业务账户下的文件,所以这样的程序只能将配置文件保存到每个业务系统中,使用非常繁琐。

Hugo的方式

在使用 Hugo 过程中,发现 Hugo 仅使用一个二进制程序就能自动生成多种代码模板,一定是将模板编译到程序中。

研究 Hugo 源码发现,Hugo 使用 go generate 根据模板 HTML 文件生成 Go 源码文件 templates.autogen.go,将模板集成到代码中。

生成程序参见

https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/embedded/generate/generate.go

核心是将模板保存到下面的数组中。

var EmbeddedTemplates = [][2]string{
  { 'template name', 'template content' }
}

数组元素是二维字符串数组,包括模板名称和模板内容。

文件中使用 go generate 的注释语法,支持使用 go generate 直接运行,生成文件。

//go:generate go run generate.go

package main

// ...

func main() {
    // ...
}

生成的文件参见

https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/embedded/templates.autogen.go

可以使用这种方式,将配置文件集成到二进制程序中。

使用go generate集成YAML配置文件

使用 Hugo 集成 HTML 模板的方式,在 nwpc-oper/nwpc-data-client 项目中将 YAML 配置文件内嵌到程序中。

程序会遍历配置文件目录,读取所有的 YAML 文件,并保存到下面的数组中。

var EmbeddedConfigs = [][2]string{
  { "extended data type", "config content" }
}

数组元素是二维字符串数组,包括数据类型和配置文件内容。

命令在执行时会检测用户是否提供配置文件路径,如果没有提供,则使用内置的配置文件中。

具体代码如下:

https://github.com/nwpc-oper/nwpc-data-client/blob/master/common/config/generate/generate.go

在该文件目录执行

go generate

会生成内嵌配置文件的代码,如下所示:

https://github.com/nwpc-oper/nwpc-data-client/blob/master/common/config/config.autogen.go