使用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