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

目录

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

使用配置文件的常见方式

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

固定目录

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

环境变量

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

命令行参数指定

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

我常使用的方法

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

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

#!/usr/bin/env bash
export ECFLOW_CHECKER_CONFIG_PATH=/g3/wangdp/project/work/nost-go/ecflow-client-go/dist/conf
/g3/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