golang多后端配置加载与结构体映射插件库confita的使用

Golang多后端配置加载与结构体映射插件库Confita的使用

Confita是一个从多个后端加载配置并将其存储在结构体中的库。

支持的后端

  • 环境变量
  • JSON文件
  • Yaml文件
  • Toml文件
  • 命令行标志
  • etcd
  • Consul
  • Vault
  • Amazon SSM

安装

go get -u github.com/heetch/confita

使用

Confita扫描结构体中的config标签,并依次调用所有后端直到找到键。然后将值转换为字段的类型。

结构体布局

支持Go的基本类型:

type Config struct {
  Host        string        `config:"host"`
  Port        uint32        `config:"port"`
  Timeout     time.Duration `config:"timeout"`
}

默认情况下,所有字段都是可选的。使用required选项时,如果找不到键,Confita将返回错误。

type Config struct {
  Addr        string        `config:"addr,required"`
  Timeout     time.Duration `config:"timeout"`
}

也支持嵌套结构体:

type Config struct {
  Host        string        `config:"host"`
  Port        uint32        `config:"port"`
  Timeout time.Duration     `config:"timeout"`
  Database struct {
    URI string              `config:"database-uri,required"`
  }
}

如果字段是切片,Confita会自动按逗号分割配置值并用每个子值填充切片。

type Config struct {
  Endpoints []string `config:"endpoints"`
}

作为一种特殊情况,如果字段标记为"-",则该字段总是被忽略。这在你想自己填充这个字段时很有用。

type Config struct {
  // Field is ignored by this package.
  Field float64 `config:"-"`

  // Confita scans any structure recursively, the "-" value prevents that.
  Client http.Client `config:"-"`
}

加载配置

创建加载器:

loader := confita.NewLoader()

默认情况下,Confita加载器从环境中加载所有键。加载器可以将其他配置的后端作为参数。

loader := confita.NewLoader(
  env.NewBackend(),
  file.NewBackend("/path/to/config.json"),
  file.NewBackend("/path/to/config.yaml"),
  flags.NewBackend(),
  etcd.NewBackend(etcdClientv3),
  consul.NewBackend(consulClient),
  vault.NewBackend(vaultClient),
)

加载配置:

err := loader.Load(context.Background(), &cfg)

由于使用多个远程后端时加载配置可能需要时间,可以使用上下文进行超时和取消:

ctx, cancel := context.WithTimeout(context.Background(), 5 * time.Second)
defer cancel()
err := loader.Load(ctx, &cfg)

默认值

如果找不到键,Confita不会更改相应的结构体字段。考虑到这一点,可以通过在将结构体传递给Confita之前填充结构体来实现默认值。

type Config struct {
  Host        string        `config:"host"`
  Port        uint32        `config:"port"`
  Timeout     time.Duration `config:"timeout"`
  Password    string        `config:"password,required"`
}

// default values
cfg := Config{
  Host: "127.0.0.1",
  Port: "5656",
  Timeout: 5 * time.Second,
}

err := confita.NewLoader().Load(context.Background(), &cfg)

后端选项

默认情况下,Confita依次查询每个后端,直到找到键。但是,为了避免一些无用的处理,可以指定backend选项来描述期望在哪个后端找到这个键。这在事先知道键的位置时特别有用。

type Config struct {
  Host        string        `config:"host,backend=env"`
  Port        uint32        `config:"port,required,backend=etcd"`
  Timeout     time.Duration `config:"timeout"`
}

命令行标志

flags后端允许从命令行加载单个配置键。默认值从结构体字段值中提取。

也支持short选项。

为了更新命令行上的使用信息,为给定字段提供description

type Config struct {
  Host        string        `config:"host,short=h"`
  Port        uint32        `config:"port,short=p"`
  Timeout     time.Duration `config:"timeout,description=timeout (in seconds) for failure"`
}
./bin -h

Usage of ./bin:
  -host string
       (default "127.0.0.1")
  -h string
       (default "127.0.0.1")
  -port int
       (default 5656)
  -p int
       (default 5656)
  -timeout duration
       timeout (in seconds) for failure (default 10s)

完整示例

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/heetch/confita"
	"github.com/heetch/confita/backend/env"
	"github.com/heetch/confita/backend/file"
	"github.com/heetch/confita/backend/flags"
)

type Config struct {
	Host     string        `config:"host,short=h"`
	Port     uint32        `config:"port,short=p"`
	Timeout  time.Duration `config:"timeout,description=timeout (in seconds) for failure"`
	Database struct {
		URI string `config:"database-uri,required"`
	}
}

func main() {
	// 默认值
	cfg := Config{
		Host:    "127.0.0.1",
		Port:    5656,
		Timeout: 5 * time.Second,
	}

	// 创建加载器,使用环境变量、JSON文件和命令行标志
	loader := confita.NewLoader(
		env.NewBackend(),
		file.NewBackend("config.json"),
		flags.NewBackend(),
	)

	// 加载配置
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	err := loader.Load(ctx, &cfg)
	if err != nil {
		log.Fatal(err)
	}

	// 使用配置
	fmt.Printf("Host: %s\n", cfg.Host)
	fmt.Printf("Port: %d\n", cfg.Port)
	fmt.Printf("Timeout: %v\n", cfg.Timeout)
	fmt.Printf("Database URI: %s\n", cfg.Database.URI)
}

许可证

该库在MIT许可证下发布。


更多关于golang多后端配置加载与结构体映射插件库confita的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang多后端配置加载与结构体映射插件库confita的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang 多后端配置加载与结构体映射插件库 Confita 使用指南

Confita 是一个强大的 Go 语言配置加载库,支持从多种后端(如环境变量、文件、etcd 等)加载配置并映射到结构体。下面详细介绍其使用方法。

1. Confita 核心特性

  • 支持多种后端:环境变量、JSON/YAML/TOML 文件、etcd、consul 等
  • 结构体标签映射
  • 嵌套结构体支持
  • 自定义加载器
  • 配置重载功能

2. 安装 Confita

go get github.com/heetch/confita
go get github.com/heetch/confita/backend/env
go get github.com/heetch/confita/backend/file

3. 基本使用示例

3.1 定义配置结构体

type Config struct {
    Host     string        `config:"host"`
    Port     int           `config:"port"`
    Timeout  time.Duration `config:"timeout"`
    Database struct {
        Username string `config:"username"`
        Password string `config:"password"`
    } `config:"database"`
}

3.2 从多个后端加载配置

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/heetch/confita"
    "github.com/heetch/confita/backend"
    "github.com/heetch/confita/backend/env"
    "github.com/heetch/confita/backend/file"
)

func main() {
    // 定义配置结构体实例
    var cfg Config
    
    // 创建加载器,指定多个后端(优先级从高到低)
    loader := confita.NewLoader(
        env.NewBackend(),  // 环境变量
        file.NewBackend("config.json"),  // JSON文件
        file.NewBackend("config.yaml"),  // YAML文件
    )
    
    // 加载配置
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    
    if err := loader.Load(ctx, &cfg); err != nil {
        log.Fatalf("failed to load configuration: %v", err)
    }
    
    fmt.Printf("Loaded config: %+v\n", cfg)
}

4. 高级用法

4.1 自定义后端

// 实现 backend.Backend 接口
type CustomBackend struct {
    data map[string]string
}

func (b *CustomBackend) Get(ctx context.Context, key string) ([]byte, error) {
    if val, ok := b.data[key]; ok {
        return []byte(val), nil
    }
    return nil, backend.ErrNotFound
}

func main() {
    var cfg Config
    
    customBackend := &CustomBackend{
        data: map[string]string{
            "host": "custom.example.com",
            "port": "8080",
        },
    }
    
    loader := confita.NewLoader(
        customBackend,
        env.NewBackend(),
    )
    
    // 加载配置...
}

4.2 必填字段验证

type Config struct {
    // 使用 required 标签标记必填字段
    APIKey string `config:"api_key,required"`
}

4.3 默认值设置

type Config struct {
    // 设置默认值
    Timeout time.Duration `config:"timeout" default:"10s"`
}

5. 支持的标签

  • config:"key" - 指定后端中的键名
  • required - 标记字段为必填
  • default:"value" - 设置默认值
  • ignore - 忽略该字段

6. 支持的默认后端

  • env - 环境变量
  • file - 文件(JSON/YAML/TOML)
  • etcd - etcd 键值存储
  • consul - Consul 键值存储
  • flags - 命令行标志

7. 实际应用示例

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/heetch/confita"
    "github.com/heetch/confita/backend/env"
    "github.com/heetch/confita/backend/file"
)

type AppConfig struct {
    Debug    bool          `config:"debug" default:"false"`
    Server   ServerConfig  `config:"server"`
    Database DBConfig      `config:"db"`
}

type ServerConfig struct {
    Host        string        `config:"host" default:"localhost"`
    Port        int           `config:"port" default:"8080"`
    Timeout     time.Duration `config:"timeout" default:"30s"`
    EnableHTTPS bool          `config:"enable_https" default:"false"`
}

type DBConfig struct {
    URL      string `config:"url" required:"true"`
    Username string `config:"username"`
    Password string `config:"password"`
}

func main() {
    var config AppConfig
    
    loader := confita.NewLoader(
        env.NewBackend(),
        file.NewBackend("config.yaml"),
        file.NewBackend("/etc/myapp/config.yaml"),
    )
    
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    
    if err := loader.Load(ctx, &config); err != nil {
        log.Fatalf("failed to load config: %v", err)
    }
    
    fmt.Printf("Application configuration:\n%+v\n", config)
}

8. 最佳实践

  1. 为配置结构体添加合理的默认值
  2. 明确标记必填字段
  3. 按照优先级顺序排列后端
  4. 为敏感配置(如密码)考虑使用加密后端
  5. 在生产环境中使用 context 设置合理的超时

Confita 提供了灵活而强大的配置管理方案,可以很好地满足现代 Go 应用程序的配置需求。通过合理使用,可以大大简化配置管理代码,提高应用程序的可维护性。

回到顶部