配置管理
10.1 配置项介绍
Gin 框架没有自带配置管理功能,需要搭配其他库或自己写代码实现,配置项、文件格式和加载方式见下文。
10.1.1 常见的配置项
常见的配置项有:
- 服务器端口
- 日志级别
- 数据库连接信息
- 缓存配置
- 第三方服务接口信息
10.1.2 配置文件格式
常用的配置文件格式有:
- JSON
- YAML
- TOML
- INI
选哪种看项目需求和团队习惯。
10.2 配置文件解析
Gin 通常会与其他库如 Viper 或 Go's encoding/json 等搭配使用,以解析配置文件。
10.2.1 使用 Viper 解析配置
Viper 支持多种格式的配置文件,也能监听配置变更,实现动态配置管理。
go
import (
"github.com/spf13/viper"
)
type Config struct {
Server struct {
Port string
}
Database struct {
Host string
Port int
Username string
Password string
Name string
}
}
func LoadConfig() (*Config, error) {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
if err := viper.ReadInConfig(); err != nil {
return nil, err
}
var config Config
if err := viper.Unmarshal(&config); err != nil {
return nil, err
}
return &config, nil
}10.2.2 加载配置文件
在应用初始化时加载配置文件:
go
func main() {
config, err := LoadConfig()
if err != nil {
log.Fatalf("Could not load config: %v", err)
}
r := gin.Default()
r.Run(config.Server.Port)
}10.3 动态配置管理
在某些场景下,应用需要动态加载或修改配置,这可以通过文件变更监听或配置中心实现。
10.3.1 文件变更监听
使用 Viper 的文件变更监听功能,可以在配置文件修改时自动重新加载配置:
go
import (
"log"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
)
func WatchConfig(config *Config) {
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
log.Printf("Config file changed: %s", e.Name)
if err := viper.Unmarshal(config); err != nil {
log.Printf("Error reloading config: %v", err)
}
})
}
func main() {
config, err := LoadConfig()
if err != nil {
log.Fatalf("Could not load config: %v", err)
}
WatchConfig(config)
r := gin.Default()
r.Run(config.Server.Port)
}10.3.2 配置中心
对于大型分布式系统,可以使用配置中心(如 Consul、Etcd 或 Spring Cloud Config)集中管理配置,实现动态配置更新。
go
import (
"context"
"encoding/json"
"time"
"go.etcd.io/etcd/client/v3"
)
func LoadConfigFromEtcd() (*Config, error) {
cli, err := clientv3.New(clientv3.Config{
Endpoints: []string{"localhost:2379"},
DialTimeout: 5 * time.Second,
})
if err != nil {
return nil, err
}
defer cli.Close()
ctx, cancel := context.WithTimeout(context.Background(), 5 * time.Second)
resp, err := cli.Get(ctx, "/config/app")
cancel()
if err != nil {
return nil, err
}
var config Config
if err := json.Unmarshal(resp.Kvs[0].Value, &config); err != nil {
return nil, err
}
return &config, nil
}总结
配置项集中定义在一个结构体里,LoadConfig 启动时读入;要热更新就挂上 viper.WatchConfig,多实例部署则把配置挪进 etcd 这类配置中心。