Go语言学习之配置管理库Viper

一、Viper 是什么

  • Go 生态最常用配置管理库
  • 支持:yaml/json/toml/ini/env/命令行参数
  • 自动监听配置文件热更新
  • 读取配置像读对象一样简单

二、安装依赖

bash 复制代码
go get github.com/gin-gonic/gin
go get github.com/spf13/viper

栗子

bash 复制代码
yangyanping@yangyaningdeAir my-go % 
go get github.com/gin-gonic/gin
go get github.com/spf13/viper

三、项目结构(推荐)

bash 复制代码
├── config/
│   └── server.yaml   # 系统配置文件
    └── mysql.yaml    # mysql配置文件
    └── redis.yaml    # redis配置文件
    └── config.go     # 配置文件加载
├── main.go

四、配置示例

server.yaml

bash 复制代码
server:
  port: 8080
  mode: debug

mysql.yaml

bash 复制代码
mysql:
  host: 127.0.0.1
  port: 3306
  username: root
  password: Yangyanping@1981
  dbname: test

redis.yaml

bash 复制代码
redis:
  addr: localhost:6379
  password: ""
  db: 0

五、config.go 读取配置

Go 复制代码
package config

import (
	"os"
	"path/filepath"

	"github.com/spf13/viper"
)

type MySQLConfig struct {
	Host     string `yaml:"host"`
	Port     int    `yaml:"port"`
	Username string `yaml:"username"`
	Password string `yaml:"password"`
	DBName   string `yaml:"dbname"`
}

type RedisConfig struct {
	Addr     string `yaml:"addr"`
	Password string `yaml:"password"`
	DB       int    `yaml:"db"`
}

type Config struct {
	MySQL MySQLConfig `yaml:"mysql"`
	Redis RedisConfig `yaml:"redis"`
}

var AppConfig Config

func LoadConfig() {
	workDir, err := os.Getwd()
	if err != nil {
		panic("无法获取当前工作目录: " + err.Error())
	}

	configDir := filepath.Join(workDir, "config")
	viper.AddConfigPath(configDir)
	viper.SetConfigType("yaml")

	// 加载 server.yml 配置
	viper.SetConfigName("server")
	if err := viper.ReadInConfig(); err != nil {
		panic("无法读取 server 配置文件: " + err.Error())
	}

	// 加载 mysql.yaml 配置并合并
	viper.SetConfigName("mysql")
	if err := viper.MergeInConfig(); err != nil {
		panic("无法读取 mysql 配置文件: " + err.Error())
	}

	// 加载 redis.yaml 配置并合并
	viper.SetConfigName("redis")
	if err := viper.MergeInConfig(); err != nil {
		panic("无法读取 redis 配置文件: " + err.Error())
	}

	if err := viper.Unmarshal(&AppConfig); err != nil {
		panic("配置反序列化失败: " + err.Error())
	}
}

五、main.go 完整使用示例

Go 复制代码
package main

import (
	"my-go/config"
	"my-go/router"

	"my-go/logs"

	"my-go/database"

	"github.com/gin-gonic/gin"
)

func main() {
	gin.SetMode(gin.ReleaseMode)

	// 初始化日志库
	logs.InitLogger()
	// 加载配置文件
	config.LoadConfig()

	// 初始化数据库
	database.InitDB()
	// 初始化 Redis
	database.InitRedis()

	defer database.CloseDB()

	router := router.SetupRouter()
	router.Use(logs.GinZapLogger()) // 使用 Zap 替代默认 Logger
	router.Use(gin.Recovery())      // Recovery 仍然保留

	// 注册路由...
	router.Run(":8080")
	logs.Logger.Info("服务器已启动,prot:8080")
}

六、Viper 常用读取方法

复制代码
// 字符串
viper.GetString("server.port")

// 数字
viper.GetInt("mysql.port")

// 布尔
viper.GetBool("redis.enable")

// 子树
mysql := viper.Sub("mysql")
host := mysql.GetString("host")

// 读取环境变量
viper.AutomaticEnv()
port := viper.Get("PORT")

七、热加载配置(常用)

复制代码
// 监听配置变化
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
	fmt.Println("配置文件已修改:", e.Name)
	// 重新解析
	if err := viper.Unmarshal(&AppConfig); err != nil {
		fmt.Println("重新加载失败", err)
	}
})

八、多环境配置(开发 / 测试 / 生产)

复制代码
// 从环境变量读取 mode
mode := viper.Get("MODE")
viper.SetConfigName("config." + mode)
// 然后读取 config.dev.yaml / config.prod.yaml
相关推荐
yaoxin5211235 小时前
434. Java 日期时间 API - Period 基于日期的时间段
java·开发语言·python
凡人叶枫6 小时前
Effective C++ 条款30:透彻了解 inlining 的里里外外
linux·开发语言·c++·嵌入式开发·effective c++
学逆向的6 小时前
C++纯虚函数
开发语言·c++·网络安全
程序员二叉7 小时前
【JUC】ThreadLocal底层原理|内存泄漏|弱引用|跨线程传递方案
java·开发语言·面试·职场和发展·juc
程序员二叉7 小时前
【JUC】线程池全套深度详解|参数|流程|拒绝策略|调优|异常处理
java·开发语言·jvm·算法·面试·juc
凡人叶枫7 小时前
Effective C++ 条款22:将成员变量声明为 private
linux·开发语言·c++
Qt程序员7 小时前
掌握 Linux 内核调度:从原理到实现(进程篇)
java·开发语言
code bean8 小时前
【LangChain】检索器完全指南:从向量检索到生产级 RAG 架构
java·开发语言·微服务
LabVIEW开发8 小时前
LabVIEW + MATLAB 混合编程:爆炸场测试数据精准采集方案
开发语言·matlab·labview
嵌入式协会20240728 小时前
(已解决)MinIO python 获取预签名出现forbidden、errornetwork等错误
java·开发语言·python