增加配置文件

This commit is contained in:
2026-06-02 13:52:47 +08:00
parent 6117222625
commit aab3aeb5b2
31 changed files with 3326 additions and 198 deletions
+124 -8
View File
@@ -1,8 +1,13 @@
package config
import (
"fmt"
"log/slog"
"os"
"strconv"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
)
type Config struct {
@@ -28,30 +33,141 @@ type AppConfig struct {
Theme string
}
var globalConfig *Config
// Load 加载配置(支持环境变量和配置文件)
func Load() *Config {
port, _ := strconv.Atoi(getEnv("SERVER_PORT", "8080"))
// 1. 初始化 viper
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath("./config")
viper.AddConfigPath(".")
// 2. 设置默认值
setDefaults()
// 3. 自动读取环境变量
viper.AutomaticEnv()
viper.SetEnvPrefix("GOBLOG")
// 4. 读取配置文件(如果存在)
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
slog.Warn("读取配置文件失败,使用默认配置", "error", err)
}
} else {
slog.Info("配置文件加载成功", "file", viper.ConfigFileUsed())
}
// 5. 解析配置
cfg := parseConfig()
globalConfig = cfg
// 6. 监听配置变更
watchConfig()
return cfg
}
// setDefaults 设置默认配置值
func setDefaults() {
viper.SetDefault("server.port", 8080)
viper.SetDefault("server.mode", "debug")
viper.SetDefault("database.driver", "sqlite")
viper.SetDefault("database.dsn", "goblog.db")
viper.SetDefault("app.name", "GoBlog")
viper.SetDefault("app.description", "一个简洁的个人博客")
viper.SetDefault("app.author", "Admin")
viper.SetDefault("app.theme", "default")
}
// parseConfig 解析配置到结构体
func parseConfig() *Config {
port := viper.GetInt("server.port")
if port == 0 {
port, _ = strconv.Atoi(getEnv("SERVER_PORT", "8080"))
}
return &Config{
Database: DatabaseConfig{
Driver: getEnv("DB_DRIVER", "sqlite"),
DSN: getEnv("DB_DSN", "goblog.db"),
Driver: viper.GetString("database.driver"),
DSN: viper.GetString("database.dsn"),
},
Server: ServerConfig{
Port: port,
Mode: getEnv("GIN_MODE", "debug"),
Mode: viper.GetString("server.mode"),
},
App: AppConfig{
Name: getEnv("APP_NAME", "GoBlog"),
Description: getEnv("APP_DESC", "一个简洁的个人博客"),
Author: getEnv("APP_AUTHOR", "Admin"),
Theme: getEnv("APP_THEME", "default"),
Name: viper.GetString("app.name"),
Description: viper.GetString("app.description"),
Author: viper.GetString("app.author"),
Theme: viper.GetString("app.theme"),
},
}
}
// watchConfig 监听配置文件变更
func watchConfig() {
viper.OnConfigChange(func(e fsnotify.Event) {
slog.Info("配置文件已变更", "file", e.Name, "operation", e.Op.String())
// 重新解析配置
globalConfig = parseConfig()
slog.Info("配置已重新加载",
"theme", globalConfig.App.Theme,
"port", globalConfig.Server.Port,
)
})
viper.WatchConfig()
}
// GetGlobalConfig 获取全局配置(可用于热更新场景)
func GetGlobalConfig() *Config {
return globalConfig
}
// getEnv 获取环境变量
func getEnv(key, defaultValue string) string {
if value := os.Getenv(key); value != "" {
return value
}
return defaultValue
}
// CreateDefaultConfig 创建默认配置文件
func CreateDefaultConfig() error {
configDir := "./config"
if _, err := os.Stat(configDir); os.IsNotExist(err) {
if err := os.MkdirAll(configDir, 0755); err != nil {
return fmt.Errorf("创建配置目录失败: %w", err)
}
}
configPath := configDir + "/config.yaml"
if _, err := os.Stat(configPath); err == nil {
return nil // 配置文件已存在
}
defaultConfig := `# GoBlog 配置文件
server:
port: 8080
mode: debug # debug 或 release
database:
driver: sqlite # sqlite 或 mysql
dsn: goblog.db # SQLite文件路径或MySQL DSN
app:
name: GoBlog
description: 一个简洁的个人博客
author: Admin
theme: default # 主题名称
`
if err := os.WriteFile(configPath, []byte(defaultConfig), 0644); err != nil {
return fmt.Errorf("创建配置文件失败: %w", err)
}
slog.Info("已创建默认配置文件", "file", configPath)
return nil
}
+14
View File
@@ -0,0 +1,14 @@
# GoBlog 配置文件
server:
port: 8080
mode: debug # debug 或 release
database:
driver: sqlite # sqlite 或 mysql
dsn: goblog.db # SQLite文件路径或MySQL DSN
app:
name: GoBlog
description: 一个简洁的个人博客
author: Admin
theme: default # 主题名称