一个可扩展的、简单的配置读取库,默认支持 .json、.xml 的配置。
所有以 "#" 开头的行都将认为是注释。
// 读取并解析配置文件 // confName :相对于 conf/ 目录的文件路径 // 也支持使用绝对路径 Parse(confName string, obj interface{})error // 使用绝对/相对 读取并解析配置文件 ParseByAbsPath(confAbsPath string, obj interface{}) error // ParseBytes 解析bytes // fileExt 是文件后缀,如.json、.toml ParseBytes(fileExt string,content []byte,obj interface{})error // 配置文件是否存在 Exists(confName string) bool // 注册一个指定后缀的配置的parser // 如要添加 .ini 文件的支持,可在此注册对应的解析函数即可 RegisterParser(fileExt string, fn ParserFn) error // 注册一个 Hook RegisterHook(h Helper) error
// NewDefault 创建一个新的配置解析实例 // 会注册默认的配置解析方法和辅助方法 func NewDefault() *Configure
若对象实现 AutoChecker 接口,当解析完成后会自动调用 AutoCheck 方法
// AutoChecker 当配置解析完成后,用于自动校验 type AutoChecker interface { AutoCheck() error }
package main import ( "fmt" "log" "github.com/fsgo/fsconf" ) type Hosts []Host type Host struct { IP string Port int } func main() { var hs Hosts // 默认是从 conf 目录里读取配置 if err := fsconf.Parse("hosts.json", &hs); err != nil { log.Fatal(err) } // 读取当前目录下的 hosts.json // fsconf.Parse("./hosts.json", &hs) // 读取上级目录的 hosts.json // fsconf.Parse("../hosts.json", &hs) fmt.Println("hosts:", hs) }
为了减少依赖,默认只支持 .json、.xml 后缀格式的文件解析,.toml、.yml文件格式的支持放在单独的子 module 中。
同时默认的 Validator 也未初始化,即默认为 nil。
若需要使用,可以导入 confext 子模块:
import "github.com/fsgo/fsconf/confext" func init(){ confext.Init() }
导入后,默认的 Validator 会被替换为 github.com/go-playground/validator/v10
配置内容:
# 若环境变量里有 server_port,而且不为空,则使用环境变量的值,否则使用默认值8080 port = "{osenv.server_port|8080}" port2 = "{osenv.server_port2}"
这样就可以在运行前通过设置环境变量来影响配置文件:
export server_port=80
go run main.go考虑到不同子模块读取配置的目录可能不同,允许让模块自己设置读取配置文件的根目录。
conf:=fsconf.NewDefault() env:=fsenv.NewAppEnv(fsenv.Value{RootDir:"./testdata/"}) conf.SetEnv(env) // your code var confData map[string]string conf.Parse("abc.json",&confData)
配置注释:每行以#开头的是注释,在解析时会忽略掉,如:
{
"ID": 1
#这是注释
# 这也是注释
}# 补充上 app 的log 目录的路径 LogFilePath = "{fsenv.LogRootDir}/http/access.log"
支持:
{fsenv.RootDir}、{fsenv.IDC}、{fsenv.DataRootDir}、
{fsenv.ConfRootDir}、{fsenv.LogRootDir}、{fsenv.RunMode} 。
不支持其他的 key,否则将报错
该功能默认不开启,需要在文件头部以注释形式声明启用。
# hook.template Enable=true支持使用 template 表达式: https://pkg.go.dev/text/template
额外扩展新增了如下函数:
// 包含子文件,支持一个或子目录下多个文件 // 若文件不存在,会报错 "include": func(name string) (string, error) { return h.fnInclude(ctx, name, hp, tp) }, "osenv": func(name string) string { return os.Getenv(name) }, "contains": func(s string, sub string) bool { return strings.Contains(s, sub) }, "prefix": func(s string, prefix string) bool { return strings.HasPrefix(s, prefix) }, "suffix": func(s string, suffix string) bool { return strings.HasSuffix(s, suffix) },
内置如下变量:
data["IDC"] = ce.IDC() data["RootDir"] = ce.RootDir() data["ConfRootDir"] = ce.ConfRootDir() data["LogRootDir"] = ce.LogRootDir() data["DataRootDir"] = ce.DataRootDir() data["RunMode"] = string(ce.RunMode())
如 a.toml 文件内容:
# hook.template Enable=true A="123" {{ include "sub/*.toml" }} # 若当前 IDC 是 bj,则会输出 IDC 字段 {{ if eq .IDC "bj" }} IDC="bj" {{ end }}
sub/b.toml 文件内容:
B=100
最终等效于(a.toml):
# hook.template Enable=true A="123" B=100 IDC="bj"