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"` } // 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"` } // 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, }, } } 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 }