package config import ( "strings" "github.com/spf13/viper" ) type Config struct { Server ServerConfig `mapstructure:"server"` Log LogConfig `mapstructure:"log"` Cors CorsConfig `mapstructure:"cors"` } type ServerConfig struct { Port int `mapstructure:"port"` Mode string `mapstructure:"mode"` ReadTimeout string `mapstructure:"read_timeout"` WriteTimeout string `mapstructure:"write_timeout"` } type LogConfig struct { Level string `mapstructure:"level"` Encoding string `mapstructure:"encoding"` } type CorsConfig struct { AllowOrigins []string `mapstructure:"allow_origins"` AllowMethods []string `mapstructure:"allow_methods"` AllowHeaders []string `mapstructure:"allow_headers"` } var C *Config func Load() (*Config, error) { viper.SetConfigName("config") viper.SetConfigType("yaml") viper.AddConfigPath("./config") viper.AddConfigPath(".") viper.SetDefault("server.port", 8080) viper.SetDefault("server.mode", "debug") viper.SetDefault("log.level", "debug") viper.SetDefault("log.encoding", "console") viper.AutomaticEnv() viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) // 允许 PORT 等环境变量直接覆盖 _ = viper.BindEnv("server.port", "PORT") if err := viper.ReadInConfig(); err != nil { // 配置文件不存在时使用默认值+环境变量,不视为致命错误 if _, ok := err.(viper.ConfigFileNotFoundError); !ok { return nil, err } } var cfg Config if err := viper.Unmarshal(&cfg); err != nil { return nil, err } C = &cfg return &cfg, nil }