package config import ( "fmt" "strings" "git.hujye.com/infrastructure/go-web-gin/env" "github.com/spf13/viper" ) var ( globalConfig *Config viperInstance *viper.Viper ) // Config represents the application configuration type Config struct { Server ServerConfig `mapstructure:"server"` App AppConfig `mapstructure:"app"` Log LogConfig `mapstructure:"log"` MySQL MySQLConfig `mapstructure:"mysql"` Redis RedisConfig `mapstructure:"redis"` } // ServerConfig represents server configuration type ServerConfig struct { Port int `mapstructure:"port"` Host string `mapstructure:"host"` Mode string `mapstructure:"mode"` // debug, release, test } // AppConfig represents application configuration type AppConfig struct { Name string `mapstructure:"name"` Environment string `mapstructure:"environment"` LogLevel string `mapstructure:"log_level"` } // LogConfig represents log configuration type LogConfig struct { OutputToFile bool `mapstructure:"output_to_file"` Filename string `mapstructure:"filename"` MaxSize int `mapstructure:"max_size"` MaxBackups int `mapstructure:"max_backups"` MaxAge int `mapstructure:"max_age"` Compress bool `mapstructure:"compress"` } // MySQLConfig represents mysql configuration type MySQLConfig struct { Host string `mapstructure:"host"` Port int `mapstructure:"port"` User string `mapstructure:"user"` Password string `mapstructure:"password"` DBName string `mapstructure:"db_name"` Charset string `mapstructure:"charset"` ParseTime bool `mapstructure:"parse_time"` MaxIdleConns int `mapstructure:"max_idle_conns"` MaxOpenConns int `mapstructure:"max_open_conns"` ConnMaxLifetime int `mapstructure:"conn_max_lifetime"` // seconds } // RedisConfig represents redis configuration type RedisConfig struct { Addr string `mapstructure:"addr"` Password string `mapstructure:"password"` DB int `mapstructure:"db"` PoolSize int `mapstructure:"pool_size"` MinIdleConns int `mapstructure:"min_idle_conns"` MaxRetries int `mapstructure:"max_retries"` DialTimeout int `mapstructure:"dial_timeout"` // seconds ReadTimeout int `mapstructure:"read_timeout"` // seconds WriteTimeout int `mapstructure:"write_timeout"` // seconds } // Load loads configuration from environment variable CFG_PATH // Default path is config/config.yml func Load() (*Config, error) { v := viper.New() v.SetConfigFile(env.GetCfgPath()) v.SetConfigType("yaml") // Read environment variables v.AutomaticEnv() v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) // Read config file if err := v.ReadInConfig(); err != nil { return nil, fmt.Errorf("failed to read config file: %w", err) } var cfg Config if err := v.Unmarshal(&cfg); err != nil { return nil, fmt.Errorf("failed to unmarshal config: %w", err) } globalConfig = &cfg viperInstance = v return &cfg, nil } // Get returns the global configuration // Must call Load first func Get() *Config { if globalConfig == nil { // Return default config if not loaded return &Config{ Server: ServerConfig{ Port: 8080, Host: "0.0.0.0", Mode: "debug", }, App: AppConfig{ Name: "go-web-gin", Environment: string(env.Local), LogLevel: "info", }, Log: LogConfig{ OutputToFile: true, Filename: "logs/app.log", MaxSize: 100, MaxBackups: 3, MaxAge: 28, Compress: true, }, MySQL: MySQLConfig{ Host: "127.0.0.1", Port: 3306, User: "root", Password: "", DBName: "test", Charset: "utf8mb4", ParseTime: true, MaxIdleConns: 10, MaxOpenConns: 100, ConnMaxLifetime: 3600, }, Redis: RedisConfig{ Addr: "127.0.0.1:6379", Password: "", DB: 0, PoolSize: 10, MinIdleConns: 5, MaxRetries: 3, DialTimeout: 5, ReadTimeout: 3, WriteTimeout: 3, }, } } return globalConfig } // GetAddr returns the server address (host:port) func (c *Config) GetAddr() string { return fmt.Sprintf("%s:%d", c.Server.Host, c.Server.Port) } // IsDebug returns true if server mode is debug func (c *Config) IsDebug() bool { return c.Server.Mode == "debug" } // IsRelease returns true if server mode is release func (c *Config) IsRelease() bool { return c.Server.Mode == "release" } // GetString returns a custom string config value by key // Supports dot notation for nested keys, e.g. "database.host" func GetString(key string) string { if viperInstance != nil { return viperInstance.GetString(key) } return "" } // GetInt returns a custom int config value by key func GetInt(key string) int { if viperInstance != nil { return viperInstance.GetInt(key) } return 0 } // GetBool returns a custom bool config value by key func GetBool(key string) bool { if viperInstance != nil { return viperInstance.GetBool(key) } return false } // GetStringSlice returns a custom string slice config value by key func GetStringSlice(key string) []string { if viperInstance != nil { return viperInstance.GetStringSlice(key) } return nil } // GetValue returns a custom config value of any type by key func GetValue(key string) any { if viperInstance != nil { return viperInstance.Get(key) } return nil } // Viper returns the underlying viper instance for advanced usage func Viper() *viper.Viper { return viperInstance }