Skip to content

kordar/gocfg

Repository files navigation

gocfg

gocfg 是一个基于 viper 的配置管理库,旨在提供更灵活的配置加载、合并及分组功能。它支持多文件扫描、环境区分、动态更新以及线程安全的配置访问。当前实现已进行专业化重构:引入线程安全的 SafeConfig、集中管理的 Manager、职责单一的 Loader,并保持对外 API 的向后兼容。

特性

  • 多格式支持:默认支持 ini, yaml, yml, toml 等格式。
  • 目录扫描:支持递归扫描指定目录下的所有配置文件。
  • 环境区分:自动识别 *-dev.*, *-pro.*, *-test.* 文件,根据 PROFILE 配置加载对应环境的配置。
  • 配置分组:支持将子目录作为配置分组(Namespace),或将子目录加载为独立的配置实例。
  • 线程安全:通过 SafeConfig 提供并发安全的读写封装。
  • 集中管理:通过全局 Manager 管理默认实例与多实例。
  • 动态更新:支持运行时动态合并配置 map 或二进制数据(适配配置中心场景)。
  • 向后兼容:保留原有 Snippet 与工具函数(标记为 Deprecated),不影响现有项目运行。

安装

go get github.com/kordar/gocfg

运行环境:Go 1.21+

快速开始

1. 初始化配置

你可以加载单个文件,也可以扫描整个目录。

package main

import (
    "fmt"
    "github.com/kordar/gocfg"
)

func main() {
    // 方式一:加载单个文件
    gocfg.InitConfig("config.ini")

    // 方式二:扫描目录下所有配置文件(递归)
    // gocfg.InitConfigWithDir("./config", "yaml", "ini")

    // 获取配置
    val := gocfg.Get("app.name")
    fmt.Println(val)
}

2. 读取配置

gocfg 提供了一系列便捷函数来获取默认实例的配置:

// 获取任意类型
value := gocfg.Get("database.host")

// 获取特定前缀的配置 (约定:system.* 和 setting.*)
sysVal := gocfg.GetSystemValue("port")   // 等同于 Get("system.port")
setVal := gocfg.GetSettingValue("limit") // 等同于 Get("setting.limit")

// 获取某个 Section 下的所有配置
section := gocfg.GetSection("database")

高级用法

结构总览

  • SafeConfig:线程安全的 Viper 包装(内部封装读写锁)。
  • Manager:集中管理默认配置与多实例,提供全局单例。
  • Loader:负责目录/文件扫描、扩展名过滤、环境区分与合并。
  • Facade 层:保留 InitConfig*Get* 等函数,便于即插即用。

环境区分加载

gocfg 支持根据环境变量或基础配置中的 PROFILE 字段自动加载对应的环境配置文件。

  1. 设置环境变量(可选)

    // 假设程序启动前设置了环境变量 G_PROFILE=dev
    // 在代码中绑定环境变量前缀
    gocfg.InitEnv("G", "profile")
    // 此时 gocfg 会读取环境变量 G_PROFILE 的值,并将其映射为配置项 "profile"
  2. 配置文件命名规则

    • 通用配置:config.yaml
    • 开发环境:config-dev.yaml
    • 生产环境:config-pro.yaml
    • 测试环境:config-test.yaml
  3. 加载

    // 初始化时,gocfg 会先加载通用配置
    // 如果检测到 profile=dev (通过文件或环境变量),会自动覆盖合并 config-dev.yaml
    gocfg.InitConfigWithDir("./config", "yaml")

子目录分组 (Namespace)

如果你希望将不同目录下的配置隔离到不同的命名空间(Key)下,可以使用 InitConfigWithParentDir。这会将子目录名称作为 key,子目录下的配置内容作为 value 合并到默认配置中。

目录结构示例

config/
  ├── db/
  │   └── redis.yaml  # 内容: host: localhost
  └── app/
      └── server.yaml # 内容: port: 8080

代码示例

gocfg.InitConfigWithParentDir("./config", "yaml")

// 访问方式:目录名.配置Key
redisHost := gocfg.Get("db.host")
serverPort := gocfg.Get("app.port")

多实例管理 (Snippet)

除了默认的全局配置对象,你还可以创建独立的配置实例。InitConfigWithSubDir 会将每个子目录初始化为一个独立的配置实例(Snippet)。

目录结构示例

config/
  ├── i18n/
  │   └── en.yaml     # 内容: welcome: "Hello"
  └── modules/
      └── payment.yaml

代码示例

// 将 config 目录下的每个子目录初始化为一个独立的 Snippet
gocfg.InitConfigWithSubDir("./config", "yaml")

// 读取 "i18n" 实例下的配置
msg := gocfg.GetM("welcome", "i18n") // 第二个参数是 Snippet 名称(子目录名)

// 读取 "modules" 实例下的配置
pay := gocfg.GetM("payment.method", "modules")

动态配置更新

支持在运行时动态写入或更新配置,适用于从配置中心拉取配置的场景。

// 动态写入配置 Map
gocfg.WriteConfigMap(map[string]interface{}{
    "new_feature": map[string]interface{}{
        "enabled": true,
    },
})

// 更新单个值
gocfg.UpdateValue("app.status", "running")

使用 Loader/Manager(进阶)

// 直接使用 Loader 自定义加载策略
ldr := gocfg.NewLoader("", "yaml", "ini")
v := gocfg.GlobalManager().Default().Viper()
_ = ldr.LoadFromDir(v, "./config")

// 管理多实例
cfg := gocfg.GlobalManager().Get("i18n")
_ = ldr.LoadFromDir(cfg.Viper(), "./config/i18n")
msg := cfg.Viper().GetString("welcome")

日志

  • 内部日志基于标准库 log/slog,不再依赖第三方日志库。
  • 你可以在应用启动时自定义 slog 的默认 handler,以控制日志格式与级别。
package main

import (
    "log/slog"
    "os"
)

func main() {
    // 使用 JSON 日志
    slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, nil)))
    // 或使用文本日志
    // slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, nil)))
}

兼容性与迁移

  • Snippet 已由 SafeConfig 替代,旧类型仍可用(作为别名),旧方法保留但标记为 Deprecated。
  • 全局多实例的分散管理已合并至 Manager,旧的多实例工具函数仍可用。
  • util.go 中的加载函数保留兼容层,内部已切换到 Loader 实现。

接口说明

gocfg 定义了 Cfg 接口,方便依赖注入和测试。

type Cfg interface {
    Name() string
    Viper(args ...interface{}) *viper.Viper
    Get(key string, args ...interface{}) interface{}
    GetSystemValue(key string, args ...interface{}) string
    GetSettingValue(key string, args ...interface{}) string
    // ... 其他方法
}
  • LocalCfg:包装单个配置实例的对象。
  • MultipleCfg:管理多个配置实例的对象,支持通过参数切换不同的配置组。
  • SafeConfig:线程安全的底层配置容器(新引入,面向并发安全与可维护性)。

许可证

MIT

About

一个基于 viper 的 Go 配置管理库,提供更灵活的配置加载、合并、分组及动态更新能力。

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages