xcfg

package
v0.0.0-...-b147793 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 7, 2025 License: BSD-3-Clause Imports: 16 Imported by: 1

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. 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"

4. 数据校验( 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 `validator:"required"` // A 字段必填,不能为空
}

具体顺序为:

  1. Validator
  2. AutoChecker

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Exists

func Exists(path string) bool

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

func MustParse(path string, obj any)

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

func MustParseBytes(ext string, content []byte, obj any)

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

func MustWithDecoder(ext string, fn xcodec.Decoder)

MustWithDecoder 注册一个解析器,若返回的 err!=nil 则 panic

func MustWithHook

func MustWithHook(hooks ...Hook)

MustWithHook 注册一个辅助类,若失败会 panic

func Parse

func Parse(path string, obj any) error

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

func ParseBytes(ext string, content []byte, obj any) error

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

func WithDecoder

func WithDecoder(ext string, fn xcodec.Decoder) error

WithDecoder 注册一个解析器

ext: 文件后缀,如 .json

func WithHook

func WithHook(hooks ...Hook) error

WithHook 注册辅助类 / Hook

Types

type Configure

type Configure struct {
	// Dir 配置的根目录,可选,当为空时,会使用 xattr.ConfDir()
	Dir string
	// contains filtered or unexported fields
}

func CloneWithContext

func CloneWithContext(ctx context.Context) *Configure

CloneWithContext (全局)返回新的对象,并设置新的 ctx

func CloneWithHook

func CloneWithHook(hooks ...Hook) *Configure

CloneWithHook (全局)返回新的对象,并注册 Hook

func Default

func Default() *Configure

Default 默认的 Configure 实例

func NewDefault

func NewDefault() *Configure

NewDefault 创建一个新的配置解析实例 会注册默认的配置解析方法和辅助方法

func SetDefault

func SetDefault(cfg *Configure) (old *Configure)

func (*Configure) Clone

func (c *Configure) Clone() *Configure

func (*Configure) CloneWithContext

func (c *Configure) CloneWithContext(ctx context.Context) *Configure

func (*Configure) CloneWithHook

func (c *Configure) CloneWithHook(hooks ...Hook) *Configure

func (*Configure) Exists

func (c *Configure) Exists(path string) bool

func (*Configure) MusWithHook

func (c *Configure) MusWithHook(hooks ...Hook)

MusWithHook 注册新的 Hook, 若出现重名等异常情况会 panic

func (*Configure) MustWithDecoder

func (c *Configure) MustWithDecoder(ext string, fn xcodec.Decoder)

func (*Configure) Parse

func (c *Configure) Parse(path string, obj any) error

func (*Configure) ParseBytes

func (c *Configure) ParseBytes(ext string, content []byte, obj any) error

func (*Configure) WithDecoder

func (c *Configure) WithDecoder(ext string, fn xcodec.Decoder) error

func (*Configure) WithHook

func (c *Configure) WithHook(hooks ...Hook) error

WithHook 注册新的 Hook,若出现重名会注册失败

type Hook

type Hook interface {
	// Name 名称,不可为空
	// 每个 Hook 应返回唯一的名称,若重名会注册失败
	Name() string

	// Execute 对读取的配置内容加工的逻辑
	Execute(ctx context.Context, p *HookParam) (output []byte, err error)
}

Hook 辅助类,用于在解析配置文件内容是,提前先对配置的内容进行预处理

type HookParam

type HookParam struct {
	Cfg      *Configure // 当前 Cfg 对象
	FileExt  string     // 文件类型后缀,如 .toml,.json
	FilePath string     // 文件路径。当直接解析内容时,为空字符串
	Content  []byte     // 文件内容
}

HookParam Hook 的参数

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL