golang统一读取多源配置数据的插件库go-cfg的使用

Golang统一读取多源配置数据的插件库go-cfg的使用

简介

go-cfg是一个用于从多种来源(如环境变量、命令行标志和配置文件)读取配置数据的Go库。该库提供了统一的接口来读取配置数据,使得管理和维护应用程序配置更加容易。

安装

使用以下命令安装库:

go get github.com/dsbasko/go-cfg

使用示例

基本用法

package main

import (
	"github.com/dsbasko/go-cfg"
)

type Config struct {
	Mode string `default:"prod" json:"mode" yaml:"mode" s-flag:"m" flag:"mode" env:"MODE" description:"mode of the application (dev|prod)"`
	HTTP struct {
		Host         string `default:"localhost" json:"host" yaml:"host" s-flag:"h" flag:"http-host" env:"HTTP_HOST"`
		Port         int    `default:"3000" json:"port" yaml:"port" s-flag:"p" flag:"http-port" env:"HTTP_PORT"`
		ReadTimeout  int    `json:"read_timeout" yaml:"read-timeout" flag:"http-read-timeout" env:"HTTP_READ_TIMEOUT"`
		WriteTimeout int    `json:"write_timeout" yaml:"write-timeout" flag:"http-write-timeout" env:"HTTP_WRITE_TIMEOUT"`
	} `json:"http" yaml:"http"`
}

func main() {
	cfg := Config{}

	gocfg.MustReadFile("configs/config.yaml", &cfg)
	gocfg.MustReadEnv(&cfg)
	gocfg.MustReadFlag(&cfg)
}

命令行标志

type config struct {
	WithShort string `s-flag:"s" flag:"with-short" description:"With short flag"`
	Flat      string `flag:"flat" description:"Flat flag"`
	Parent    struct {
		Nested string `flag:"nested" description:"Nested flag"`
	}
}

func main() {
	var cfg config
	if err := gocfg.ReadFlag(&cfg); err != nil {
		log.Panicf("failed to read flag: %v", err)
	}
	// 或者: gocfg.MustReadFlag(&cfg)

	log.Printf("WithShort: %v\n", cfg.WithShort)
	log.Printf("Flat: %v\n", cfg.Flat)
	log.Printf("Nested: %v\n", cfg.Parent.Nested)
}

环境变量

type config struct {
	Flat   string `env:"FLAT"`
	Parent struct {
		Nested string `env:"NESTED"`
	}
}

func main() {
	var cfg config
	if err := gocfg.ReadEnv(&cfg); err != nil {
		log.Panicf("failed to read env: %v", err)
	}
	// 或者: gocfg.MustReadEnv(&cfg)

	log.Printf("Flat: %v\n", cfg.Flat)
	log.Printf("Nested: %v\n", cfg.Parent.Nested)
}

配置文件

type config struct {
	Flat   string `yaml:"flat"`
	Parent struct {
		Nested string `yaml:"nested"`
	}
}

func main() {
	var cfg config
	if err := gocfg.ReadFile(path.Join("cmd", "config.yaml"), &cfg); err != nil {
		log.Panicf("failed to read config.yaml file: %v", err)
	}
	// 或者: gocfg.MustReadFile(path.Join("cmd", "config.yaml"), &cfg)

	log.Printf("Flat: %v\n", cfg.Flat)
	log.Printf("Nested: %v\n", cfg.Parent.Nested)
}

对应的YAML配置文件内容:

flat: f1
foo:
  nested: n1

结构体标签说明

命令行标志标签

  • default: 默认值
  • flag: 标志名称
  • s-flag: 短标志名(1个字符)
  • description: 标志描述,在使用--help命令时显示

环境变量标签

  • default: 默认值
  • env: 环境变量名称

配置文件标签

  • default: 默认值
  • env: 用于.env格式文件
  • yaml: 用于.yaml.yml格式文件
  • toml: 用于.toml格式文件
  • json: 用于.json格式文件

注意事项

该库使用了env、pflag、yaml、toml和godotenv的代码库来处理环境变量和标志。这是一个临时解决方案,未来可能会实现自己的版本。感谢这些库的作者所做的工作!


更多关于golang统一读取多源配置数据的插件库go-cfg的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang统一读取多源配置数据的插件库go-cfg的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


go-cfg: Golang统一读取多源配置数据的插件库

go-cfg 是一个用于统一读取多种配置源数据的Golang库,它提供了简洁的API来从不同来源(如文件、环境变量、命令行参数等)加载配置,并支持配置合并和优先级设置。

主要特性

  1. 支持多种配置源:JSON、YAML、TOML、环境变量、命令行参数等
  2. 配置合并功能,支持设置优先级
  3. 支持配置热更新
  4. 简单易用的API
  5. 支持自定义配置源

安装

go get github.com/go-cfg/cfg

基本使用示例

package main

import (
	"fmt"
	"log"
	
	"github.com/go-cfg/cfg"
)

type Config struct {
	Server struct {
		Host string `json:"host" yaml:"host" env:"SERVER_HOST"`
		Port int    `json:"port" yaml:"port" env:"SERVER_PORT"`
	} `json:"server" yaml:"server"`
	Database struct {
		URL      string `json:"url" yaml:"url" env:"DB_URL"`
		Username string `json:"username" yaml:"username" env:"DB_USER"`
		Password string `json:"password" yaml:"password" env:"DB_PASS"`
	} `json:"database" yaml:"database"`
}

func main() {
	var config Config
	
	// 创建配置加载器
	loader := cfg.New(
		// 从环境变量加载
		cfg.WithEnv(),
		// 从JSON文件加载
		cfg.WithFile("config.json", cfg.JSON),
		// 从YAML文件加载
		cfg.WithFile("config.yaml", cfg.YAML),
	)
	
	// 加载配置
	if err := loader.Load(&config); err != nil {
		log.Fatalf("Failed to load config: %v", err)
	}
	
	// 使用配置
	fmt.Printf("Server: %s:%d\n", config.Server.Host, config.Server.Port)
	fmt.Printf("Database: %s@%s\n", config.Database.Username, config.Database.URL)
}

高级用法

1. 设置配置源优先级

loader := cfg.New(
	// 低优先级 - 首先尝试从JSON文件加载
	cfg.WithFile("config.json", cfg.JSON, cfg.Priority(10)),
	// 高优先级 - 然后从环境变量加载,会覆盖JSON中的配置
	cfg.WithEnv(cfg.Priority(20)),
	// 最高优先级 - 最后从命令行参数加载,会覆盖所有其他配置
	cfg.WithFlag(cfg.Priority(30)),
)

2. 配置热更新

// 创建支持热更新的加载器
loader := cfg.New(
	cfg.WithFile("config.yaml", cfg.YAML, cfg.Watch(true)),
)

var config Config
if err := loader.Load(&config); err != nil {
	log.Fatal(err)
}

// 监听配置变更
ch := loader.Watch()
go func() {
	for {
		select {
		case <-ch:
			// 配置已更新,重新加载
			if err := loader.Load(&config); err != nil {
				log.Printf("Failed to reload config: %v", err)
			} else {
				log.Println("Config reloaded successfully")
			}
		}
	}
}()

3. 自定义配置源

// 实现cfg.Source接口
type MyCustomSource struct {
	data map[string]interface{}
}

func (s *MyCustomSource) Load() (map[string]interface{}, error) {
	return s.data, nil
}

func (s *MyCustomSource) Priority() int {
	return 15
}

// 使用自定义配置源
customSource := &MyCustomSource{
	data: map[string]interface{}{
		"server": map[string]interface{}{
			"host": "custom.host",
			"port": 8080,
		},
	},
}

loader := cfg.New(
	cfg.WithSource(customSource),
)

配置合并规则

go-cfg 按照以下规则合并配置:

  1. 按优先级从低到高依次加载配置
  2. 高优先级配置会覆盖低优先级配置中的相同字段
  3. 对于嵌套结构,会递归合并
  4. 数组类型会被完全替换而不是合并

最佳实践

  1. 定义清晰的结构体来表示配置
  2. 为配置字段添加适当的标签(json、yaml、env等)
  3. 合理设置配置源优先级
  4. 生产环境中建议使用环境变量或密钥管理服务存储敏感信息
  5. 开发环境可以使用配置文件方便修改

总结

go-cfg 是一个功能强大且灵活的配置管理库,它简化了从多种来源加载和合并配置的过程。通过统一的接口,开发者可以轻松管理应用程序的配置,而无需关心底层配置源的细节。无论是小型项目还是大型分布式系统,go-cfg 都能提供良好的配置管理解决方案。

回到顶部