一个可扩展的、简单的配置读取库,默认支持 .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"