Documentation
¶
Overview ¶
Package xcfg 通用的配置解析组件,已默认内置支持 .json 和 .xml 格式的配置文件
1. 支持的文件格式 ¶
默认内置支持 .json 和 .xml 格式, 支持使用 WithParser 和 MustWithParser 注册新的解析器。
2. 配置文件路径 ¶
在使用 Parse 方法解析配置文件或者使用 Exists 判断文件是否存在时,传入的配置文件路径( path 参数) 可以是绝对路径,也可以是相对于配置文件根目录 ( 读取自 xattr.ConfDir() ) 的相对路径。 同时,文件后缀是可选的,当查找文件不存在时,会添加上支持的后缀依次去判断, 如 Exists("app.toml") 会补充为完整路径 {ConfDir}/app.json、{ConfDir}/app.xml 等去判断。
3. Hooks ¶
Hook 功能会在解析配置内容时自动运行。目前内置如下几个功能:
1. 读取环境变量的值
在配置内容中使用 {env.变量名} 或者 {env.变量名|默认值}。 变量名应该是有效的环境变量名称。 环境变量的值会使用 os.Getenv( 变量名 ) 方法读取,若环境变量不存在,会返回空字符串。 如 user.json:
{"name":"{env.userName}","age":{env.age|18}}
若有环境变量值( export userName=hello ),在解析前,配置内容会被替换为:
{"name":"hello","age":18}
2. 读取 xattr 属性的值
在配置内容中使用 {xattr.属性名},可读取到 xattr 的属性值,支持的属性名仅限如下:
RootDir : 应用根目录地址,如 /home/work/myapp IDC : 应用所属机房, 如 online DataDir : 应用数据目录地址,如 /home/work/myapp/data ConfDir : 应用配置目录地址, 如 /home/work/myapp/conf TempDir : 应用临时文件目录地址, 如 /home/work/myapp/temp LogDir : 应用日志文件目录地址, 如 /home/work/myapp/log RunMode : 应用运行模式,如 product
3. 调用标准库的 os.XXX (部分函数)
在配置内容中使用 {os.方法名},具体支持的方法名如下:
PID : 获取应用的 PID(进程ID),即调用 os.Getpid() PPID : 获取应用的 PPID(父进程ID),即调用 os.Getppid() TempDir :获取系统的临时文件目录,即调用 os.TempDir() Hostname :获取系统的主机名,即调用 os.Hostname() UserHomeDir :获取当前用户的 Home 目录,即调用 os.UserHomeDir() UserCacheDir :获取当前用户的 Cache 目录,即调用 os.UserCacheDir() UserConfigDir :获取当前用户的配置目录,即调用 os.UserConfigDir()
4. Go Template 语法
该功能默认未启用,需要在配置文件的头部添加如何内容以启用该功能:
# hook.template Enable=true
以下是一个例子 ( server.toml ):
# hook.template Enable=true
Port = {env.Port1}
{{ include "sub1/*.toml" }}
{{ include "sub2/z.toml" }}
template 语法详见 https://pkg.go.dev/text/template 。 默认内置如下自定义函数:
include : 包含指定的文件,如 include "sub2/z.toml",include "sub1/*.toml" env : 读取环境变量的值,如 env "userName" contains : 即 strings.Contains,如 contains "hello" "h" prefix : 即 strings.HasPrefix,如 contains "hello" "h" suffix : 即 strings.HasSuffix,如 contains "hello" "o"
5. 数据校验( Validator ) ¶
使用 Parser、ParseBytes 解析配置后,得的的结果可能是非预期的,如必填字段为空或者格式错误。
如典型的解析配置然后校验的逻辑为:
if err := xcfg.Parse("abc.json", &info); err != nil {
return err
}
// 下面是校验逻辑
if info.A == "" {
return fmt.Errorf("required field A is empty")
}
若 info 的 struct 对象实现了 AutoChecker 接口,则在调用 Parse 解析配置内容之后,会自动调用校验逻辑。
type AutoChecker interface {
AutoCheck() error
}
即让 info 的 struct 定义为:
type Info struct {
A string
}
func (in *Info)AutoCheck() error{
if in==nil || in.A==""{
return fmt.Errorf("invalid info")
}
return nil
}
除此之外,还可以使用 Validator 实现自动校验,使用的前提是给 DefaultValidator 赋值。 如可以使用 github.com/go-playground/validator/v10 来初始化 DefaultValidator。
type Info struct {
A string `validate:"required"` // A 字段必填,不能为空
}
具体顺序为:
- Validator
- AutoChecker
Index ¶
- func Exists(path string) bool
- func MustParse(path string, obj any)
- func MustParseBytes(ext string, content []byte, obj any)
- func MustWithDecoder(ext string, fn xcodec.Decoder)
- func MustWithHook(hooks ...Hook)
- func Parse(path string, obj any) error
- func ParseBytes(ext string, content []byte, obj any) error
- func WithDecoder(ext string, fn xcodec.Decoder) error
- func WithHook(hooks ...Hook) error
- type Configure
- func (c *Configure) Clone() *Configure
- func (c *Configure) CloneWithContext(ctx context.Context) *Configure
- func (c *Configure) CloneWithHook(hooks ...Hook) *Configure
- func (c *Configure) Exists(path string) bool
- func (c *Configure) MusWithHook(hooks ...Hook)
- func (c *Configure) MustWithDecoder(ext string, fn xcodec.Decoder)
- func (c *Configure) Parse(path string, obj any) error
- func (c *Configure) ParseBytes(ext string, content []byte, obj any) error
- func (c *Configure) WithDecoder(ext string, fn xcodec.Decoder) error
- func (c *Configure) WithHook(hooks ...Hook) error
- type Hook
- type HookParam
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Exists ¶
Exists 判断配置文件是否存在
path: 配置文件路径,可以是绝对路径,也可以是相对于 ConfDir 的相对路径。 文件后缀是可选的,当查找文件不存在时,会添加上支持的后缀依次去判断。 如 Exists("app.toml") 会补充为 完整路径 {ConfDir}/app.json、{ConfDir}/app.xml 等去判断
Example ¶
package main
import (
"fmt"
"github.com/xanygo/anygo/xcfg"
)
func main() {
// 配置文件 {ConfDir}/abc.json 存在:
fmt.Println(xcfg.Exists("abc")) // true
fmt.Println(xcfg.Exists("abc.json")) // true
// 配置文件 {ConfDir}/not-found.json 不存在:
fmt.Println(xcfg.Exists("not-found")) // false
fmt.Println(xcfg.Exists("not-found.json")) // false
}
Output: true true false false
func MustParse ¶
MustParse 调用 Parse,若返回 err != nil 则 panic
Example ¶
package main
import (
"fmt"
"github.com/xanygo/anygo/xcfg"
)
func main() {
type Info struct {
A string
}
var info Info
// 解析 配置文件 {ConfDir}/abc.json,若失败会 panic
xcfg.MustParse("abc.json", &info)
fmt.Printf("info.A = %q\n", info.A)
}
Output: info.A = "bb"
func MustParseBytes ¶
MustParseBytes 调用 ParseBytes,若返回 err!=ni 则 panic
Example ¶
package main
import (
"fmt"
"github.com/xanygo/anygo/xcfg"
)
func main() {
type User struct {
Name string
Age int
}
content := []byte(`{"Name":"Hello","age":18}`)
var user *User
xcfg.MustParseBytes(".json", content, &user) // 解析失败会 panic
fmt.Println("Name=", user.Name)
fmt.Println("Age=", user.Age)
}
Output: Name= Hello Age= 18
func MustWithDecoder ¶
MustWithDecoder 注册一个解析器,若返回的 err!=nil 则 panic
func Parse ¶
Parse 解析配置,配置文件默认认为在 conf/ 目录下, 如 有 conf/abc.toml ,则 path = "abc.toml"
Example ¶
package main
import (
"fmt"
"log"
"github.com/xanygo/anygo/xcfg"
)
func main() {
type Info struct {
A string
}
var info Info
// 解析 配置文件 {ConfDir}/abc.json
if err := xcfg.Parse("abc.json", &info); err != nil {
log.Println(err.Error())
}
fmt.Printf("info.A = %q\n", info.A)
}
Output: info.A = "bb"
func ParseBytes ¶
ParseBytes 解析 bytes 内容的配置 ext: 文件后缀,如.json、.toml
Example ¶
package main
import (
"fmt"
"log"
"github.com/xanygo/anygo/xcfg"
)
func main() {
type User struct {
Name string
Age int
}
content := []byte(`{"Name":"Hello","age":18}`)
var user *User
if err := xcfg.ParseBytes(".json", content, &user); err != nil {
log.Fatalln("ParseBytes with error:", err)
}
fmt.Println("Name=", user.Name)
fmt.Println("Age=", user.Age)
}
Output: Name= Hello Age= 18
Types ¶
type Configure ¶
type Configure struct {
// Dir 配置的根目录,可选,当为空时,会使用 xattr.ConfDir()
Dir string
// contains filtered or unexported fields
}
func CloneWithContext ¶
CloneWithContext (全局)返回新的对象,并设置新的 ctx
func SetDefault ¶
func (*Configure) CloneWithContext ¶
func (*Configure) CloneWithHook ¶
func (*Configure) MusWithHook ¶
MusWithHook 注册新的 Hook, 若出现重名等异常情况会 panic