package config import ( "fmt" "os" "path/filepath" "sync" "gopkg.in/yaml.v2" ) // Config 应用配置 type Config struct { Database DBConfig `yaml:"database"` Redis RedisConfig `yaml:"redis"` Doris DorisConfig `yaml:"doris"` RabbitMQ RabbitMQConfig `yaml:"rabbitmq"` // 新增 RabbitMQ 配置 Auth Auth `yaml:"auth"` Service Service `yaml:"service"` HTTP HTTPConfig `yaml:"http"` } // RabbitMQConfig RabbitMQ配置 type RabbitMQConfig struct { // 连接配置 Host string `yaml:"host"` Port int `yaml:"port"` Username string `yaml:"username"` Password string `yaml:"password"` Vhost string `yaml:"vhost"` // TLS配置 UseTLS bool `yaml:"use_tls"` CACert string `yaml:"ca_cert"` CertFile string `yaml:"cert_file"` KeyFile string `yaml:"key_file"` // 连接池和超时配置 MaxOpenChannels int `yaml:"max_open_channels"` // 最大通道数 ReconnectDelay int `yaml:"reconnect_delay"` // 重连延迟(毫秒) MaxReconnectAttempts int `yaml:"max_reconnect_attempts"` // 最大重试次数 // 心跳和超时 Heartbeat int `yaml:"heartbeat"` // 心跳间隔(秒) ChannelSize int `yaml:"channel_size"` // 通道缓冲区大小 // 队列和交换机默认配置 DefaultExchange string `yaml:"default_exchange"` DefaultQueue string `yaml:"default_queue"` // 消息确认模式 AutoAck bool `yaml:"auto_ack"` Mandatory bool `yaml:"mandatory"` Immediate bool `yaml:"immediate"` // QoS配置 PrefetchCount int `yaml:"prefetch_count"` // 预取数量 PrefetchSize int `yaml:"prefetch_size"` // 预取大小(字节) Global bool `yaml:"global"` // 是否是全局QoS // 发布确认 PublisherConfirms bool `yaml:"publisher_confirms"` // 是否启用发布者确认 ConfirmTimeout int `yaml:"confirm_timeout"` // 确认超时(秒) } // HTTPConfig HTTP客户端配置 type HTTPConfig struct { Timeout int `yaml:"timeout"` MaxIdleConns int `yaml:"max_idle_conns"` MaxIdleConnsPerHost int `yaml:"max_idle_conns_per_host"` IdleConnTimeout int `yaml:"idle_conn_timeout"` MaxConnsPerHost int `yaml:"max_conns_per_host"` DisableCompression bool `yaml:"disable_compression"` DisableKeepAlives bool `yaml:"disable_keep_alives"` } // DBConfig 数据库配置 type DBConfig struct { Type string `yaml:"type"` Host string `yaml:"host"` Port int `yaml:"port"` Username string `yaml:"username"` Password string `yaml:"password"` Database string `yaml:"database"` MaxOpenConns int `yaml:"max_open_conns"` MaxIdleConns int `yaml:"max_idle_conns"` ConnMaxLifetime int `yaml:"conn_max_lifetime"` } // RedisConfig Redis配置 type RedisConfig struct { Host string `yaml:"host"` Port int `yaml:"port"` Password string `yaml:"password"` DB int `yaml:"db"` PoolSize int `yaml:"pool_size"` DialTimeout int `yaml:"dial_timeout"` ReadTimeout int `yaml:"read_timeout"` WriteTimeout int `yaml:"write_timeout"` IdleTimeout int `yaml:"idle_timeout"` MaxConnAge int `yaml:"max_conn_age"` } // DorisConfig Doris配置 type DorisConfig struct { FEHost string `yaml:"fe_host"` FEPort int `yaml:"fe_port"` FEUsername string `yaml:"fe_username"` FEPassword string `yaml:"fe_password"` MySQLHost string `yaml:"mysql_host"` MySQLPort int `yaml:"mysql_port"` MaxOpenConns int `yaml:"max_open_conns"` MaxIdleConns int `yaml:"max_idle_conns"` ConnMaxLifetime int `yaml:"conn_max_lifetime"` StreamLoadTimeout int `yaml:"stream_load_timeout"` BatchSize int `yaml:"batch_size"` } // Auth 认证配置 type Auth struct { Token string `yaml:"token"` } // Service 微服务配置 type Service struct { ServiceName string `yaml:"service_name"` Port int `yaml:"port"` ReadTimeout int `yaml:"read_timeout"` WriteTimeout int `yaml:"write_timeout"` IdleTimeout int `yaml:"idle_timeout"` TrustedProxies string `yaml:"trusted_proxies"` } // 导出接口,防止外部修改 type IConfig interface { GetDatabase() DBConfig GetRedis() RedisConfig GetDoris() DorisConfig GetRabbitMQ() RabbitMQConfig // 新增获取RabbitMQ配置方法 GetAuth() Auth GetService() Service GetHTTP() HTTPConfig IsDatabaseConfigured() bool IsRedisConfigured() bool IsDorisConfigured() bool IsRabbitMQConfigured() bool // 新增检查RabbitMQ配置方法 IsHTTPConfigured() bool IsAuthConfigured() bool } // 实现接口的具体类型 type configWrapper struct { config *Config } func (cw *configWrapper) GetDatabase() DBConfig { return cw.config.Database } func (cw *configWrapper) GetRedis() RedisConfig { return cw.config.Redis } func (cw *configWrapper) GetDoris() DorisConfig { return cw.config.Doris } func (cw *configWrapper) GetRabbitMQ() RabbitMQConfig { return cw.config.RabbitMQ } func (cw *configWrapper) GetAuth() Auth { return cw.config.Auth } func (cw *configWrapper) GetService() Service { return cw.config.Service } func (cw *configWrapper) GetHTTP() HTTPConfig { return cw.config.HTTP } func (cw *configWrapper) IsDatabaseConfigured() bool { db := cw.config.Database return db.Type != "" && db.Host != "" && db.Port > 0 && db.Username != "" && db.Database != "" } func (cw *configWrapper) IsRedisConfigured() bool { redis := cw.config.Redis return redis.Host != "" && redis.Port > 0 } func (cw *configWrapper) IsDorisConfigured() bool { doris := cw.config.Doris return doris.FEHost != "" && doris.FEPort > 0 } func (cw *configWrapper) IsRabbitMQConfigured() bool { rabbit := cw.config.RabbitMQ // 基础连接配置检查 return rabbit.Host != "" && rabbit.Port > 0 } func (cw *configWrapper) IsHTTPConfigured() bool { httpCfg := cw.config.HTTP return httpCfg.Timeout > 0 } func (cw *configWrapper) IsAuthConfigured() bool { return cw.config.Auth.Token != "" } var ( instance IConfig once sync.Once initErr error ) // GetConfig 获取配置单例实例 func GetConfig() IConfig { once.Do(func() { config, err := loadConfig() if err != nil { initErr = err instance = &configWrapper{config: &Config{}} return } instance = &configWrapper{config: config} }) return instance } // GetInitError 获取初始化错误(如果有) func GetInitError() error { return initErr } // loadConfig 加载配置文件 func loadConfig() (*Config, error) { configFile, err := findConfigFile() if err != nil { return nil, err } fmt.Printf("✅ Using config file: %s\n", configFile) // 先创建带默认值的配置 config := &Config{ Service: Service{ ServiceName: "myService", Port: 8080, ReadTimeout: 30, WriteTimeout: 30, IdleTimeout: 60, TrustedProxies: "", }, Redis: RedisConfig{ Port: 6379, DB: 0, PoolSize: 10, DialTimeout: 5, ReadTimeout: 3, WriteTimeout: 3, IdleTimeout: 300, MaxConnAge: 0, }, Doris: DorisConfig{ FEPort: 8030, MySQLPort: 9030, MaxOpenConns: 20, MaxIdleConns: 10, ConnMaxLifetime: 3600, StreamLoadTimeout: 30, BatchSize: 1000, }, HTTP: HTTPConfig{ Timeout: 30, MaxIdleConns: 100, MaxIdleConnsPerHost: 10, IdleConnTimeout: 90, MaxConnsPerHost: 0, DisableCompression: false, DisableKeepAlives: false, }, RabbitMQ: RabbitMQConfig{ Port: 5672, Username: "guest", Password: "guest", Vhost: "/", UseTLS: false, MaxOpenChannels: 10, ReconnectDelay: 5000, // 5秒 MaxReconnectAttempts: 10, // 最多重试10次 Heartbeat: 30, // 30秒心跳 ChannelSize: 100, DefaultExchange: "amq.direct", DefaultQueue: "", AutoAck: false, // 默认手动确认 Mandatory: false, Immediate: false, PrefetchCount: 1, // 一次预取1条消息 PrefetchSize: 0, Global: false, PublisherConfirms: false, // 默认不启用发布确认 ConfirmTimeout: 30, // 5秒确认超时 }, } // 读取配置文件 data, err := os.ReadFile(configFile) if err != nil { return nil, fmt.Errorf("failed to read config file %s: %v", configFile, err) } err = yaml.Unmarshal(data, &config) if err != nil { return nil, fmt.Errorf("failed to parse config file: %v", err) } return config, nil } // findConfigFile 查找配置文件 func findConfigFile() (string, error) { // 1. 首先尝试可执行文件同目录 exePath, err := os.Executable() if err == nil { exeDir := filepath.Dir(exePath) configFile := filepath.Join(exeDir, "db.yaml") if _, err := os.Stat(configFile); err == nil { return configFile, nil } } // 2. 尝试环境变量指定的路径 envConfigPath := os.Getenv("DB_CONFIG_PATH") if envConfigPath != "" { if _, err := os.Stat(envConfigPath); err == nil { return envConfigPath, nil } return "", fmt.Errorf("DB_CONFIG_PATH file not found: %s", envConfigPath) } // 3. 如果都没有找到,返回错误 exeDir := "unknown" if exePath, err := os.Executable(); err == nil { exeDir = filepath.Dir(exePath) } return "", fmt.Errorf(`no configuration file found! Tried locations: 1. Executable directory: %s/db.yaml 2. Environment variable: DB_CONFIG_PATH Solutions: - Place db.yaml in the same directory as the executable - Or set DB_CONFIG_PATH environment variable to config file path Example: export DB_CONFIG_PATH=/path/to/your/db.yaml`, exeDir) }