当前位置: 首页 > article >正文

Go 语言中强大的配置管理库—Viper

Viper 是 Go 语言中强大的配置管理库,广泛用于云原生和微服务开发中。它支持多种配置文件格式(如 YAML、JSON、TOML 等)、环境变量、命令行参数以及远程配置管理。

Viper 的主要功能

1. 支持多种格式的配置文件

• YAML、JSON、TOML、HCL、Java properties 等。

2. 读取环境变量

• 支持从系统环境变量加载配置。

3. 支持命令行参数

• 可以与 pflag 或 flag 集成,读取命令行标志。

4. 动态配置更新

• 可以监听文件变化,实时更新配置。

5. 远程配置支持

• 支持从 Consul、Etcd 等远程配置服务加载配置。

6. 默认值设置

• 为配置项设置默认值,在未定义时使用。

7. 嵌套配置支持

• 支持嵌套结构的配置项。

安装

在项目中安装 Viper:

go get -u github.com/spf13/viper

基本使用示例

1. 读取 YAML 配置文件

假设有一个 config.yaml 文件:

app:
  name: "MyApp"
  version: "1.0.0"
server:
  port: 8080
  host: "localhost"

使用 Viper 读取配置:

package main

import (
    "fmt"
    "github.com/spf13/viper"
)

func main() {
    // 设置配置文件名和路径
    viper.SetConfigName("config") // 配置文件名(不包含扩展名)
    viper.SetConfigType("yaml")  // 配置文件类型
    viper.AddConfigPath(".")     // 配置文件路径

    // 读取配置
    if err := viper.ReadInConfig(); err != nil {
        panic(fmt.Errorf("fatal error reading config file: %w", err))
    }

    // 获取配置值
    appName := viper.GetString("app.name")
    appVersion := viper.GetString("app.version")
    serverPort := viper.GetInt("server.port")
    serverHost := viper.GetString("server.host")

    fmt.Printf("App: %s v%s running on %s:%d\n", appName, appVersion, serverHost, serverPort)
}

2. 设置默认值

viper.SetDefault("app.name", "DefaultApp")
viper.SetDefault("server.port", 3000)

appName := viper.GetString("app.name")      // DefaultApp
serverPort := viper.GetInt("server.port")  // 3000

3. 读取环境变量

可以绑定环境变量,便于动态设置:

package main

import (
    "fmt"
    "github.com/spf13/viper"
)

func main() {
    // 绑定环境变量
    viper.AutomaticEnv()

    // 设置别名(可选)
    _ = viper.BindEnv("server.port", "APP_SERVER_PORT")

    // 获取环境变量的值
    serverPort := viper.GetInt("server.port")
    fmt.Printf("Server Port from ENV: %d\n", serverPort)
}

运行时设置环境变量:

export APP_SERVER_PORT=9090
go run main.go
# Output: Server Port from ENV: 9090

4. 动态监听配置文件变化

支持热加载配置文件的功能:

viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
    fmt.Println("Config file changed:", e.Name)
})

5. 嵌套结构绑定

支持将配置绑定到结构体:

package main

import (
    "fmt"
    "github.com/spf13/viper"
)

type Config struct {
    App struct {
        Name    string `mapstructure:"name"`
        Version string `mapstructure:"version"`
    }
    Server struct {
        Port int    `mapstructure:"port"`
        Host string `mapstructure:"host"`
    }
}

func main() {
    viper.SetConfigFile("config.yaml")
    if err := viper.ReadInConfig(); err != nil {
        panic(fmt.Errorf("fatal error reading config file: %w", err))
    }

    var config Config
    if err := viper.Unmarshal(&config); err != nil {
        panic(fmt.Errorf("unable to decode config into struct: %w", err))
    }

    fmt.Printf("App: %s v%s running on %s:%d\n",
        config.App.Name, config.App.Version, config.Server.Host, config.Server.Port)
}

6. 命令行参数结合 pflag 使用

package main

import (
    "fmt"
    "github.com/spf13/pflag"
    "github.com/spf13/viper"
)

func main() {
    // 定义命令行标志
    pflag.Int("port", 8080, "Server port")
    pflag.Parse()

    // 将命令行标志绑定到 Viper
    _ = viper.BindPFlags(pflag.CommandLine)

    // 获取值
    serverPort := viper.GetInt("port")
    fmt.Printf("Server Port: %d\n", serverPort)
}

运行时设置参数:

go run main.go --port=9090
# Output: Server Port: 9090


http://www.kler.cn/a/460932.html

相关文章:

  • 浏览器选中文字样式
  • Spring源码分析之事件机制——观察者模式(二)
  • 【数据结构Ⅰ复习题】
  • 15. 接雨水
  • JavaScript的diff库详解(示例:vue项目实现两段字符串比对标黄功能)
  • Vue.js组件开发-使用KeepAlive缓存特定组件
  • 比较各种排序方法的实现思想、优缺点和适用场合
  • Property ‘webkit‘ does not exist on type ‘Window typeof globalThis‘.
  • 学习笔记 --C#基础其他知识点(数据结构)
  • 2024年中国新能源汽车用车发展怎么样 PaperGPT(一)
  • PbootCMS V3.2.9前台SQL注入漏洞(上)
  • XML解析
  • FreeRTOS: 中断服务例程 Interrupt Service Routine, ISR
  • 架构师之路--达梦数据库事务控制详解
  • Rust windows 环境的安装
  • 如何实现企业精准定位?解锁高效传播的新路径,媒介盒子分享
  • 高防服务器在网络游戏中起着哪些作用?
  • 滴滴Java开发面试题及参考答案 (上)
  • Fama MacBeth两步法与多因子模型的回归检验
  • iOS 18手机不越狱玩MC java版---PojavLauncher
  • 【玩转23种Java设计模式】行为型模式篇:备忘录模式
  • 26. 机器人走迷宫
  • 条款42:了解 typename 的双重含义(Understand the two meanings of typename)
  • 条款43:学习处理模板化基类内的名称(Know how to access names in templatized base classes)
  • Java中如何实现线程安全的单例模式?
  • raspberrypi-kernel