一、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
