| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- package config
-
- import (
- "fmt"
- "os"
- "path/filepath"
- "sync"
-
- "gopkg.in/yaml.v2"
- )
-
- // Config 应用配置
- type Config struct {
- Database DBConfig `yaml:"database"`
- Auth Auth `yaml:"auth"`
- Service Service `yaml:"service"`
- }
-
- // 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"` // 单位:秒
- }
-
- // Auth 认证配置
- type Auth struct {
- Token string `yaml:"token"`
- }
-
- // Service 微服务配置
- type Service struct {
- ReadTimeout int `yaml:"read_timeout"`
- WriteTimeout int `yaml:"write_timeout"`
- IdleTimeout int `yaml:"idle_timeout"`
- }
-
- // 导出接口,防止外部修改
- type IConfig interface {
- GetDatabase() DBConfig
- GetAuth() Auth
- GetService() Service
- IsDatabaseConfigured() bool
- }
-
- // 实现接口的具体类型
- type configWrapper struct {
- config *Config
- }
-
- func (cw *configWrapper) GetDatabase() DBConfig {
- return cw.config.Database
- }
-
- func (cw *configWrapper) GetAuth() Auth {
- return cw.config.Auth
- }
-
- func (cw *configWrapper) GetService() Service {
- return cw.config.Service
- }
-
- func (cw *configWrapper) IsDatabaseConfigured() bool {
- return cw.config.Database.Type != "" &&
- cw.config.Database.Host != "" &&
- cw.config.Database.Port > 0 &&
- cw.config.Database.Username != "" &&
- cw.config.Database.Database != ""
- }
-
- func (cw *configWrapper) IsAuthConfigured() bool {
- return cw.config.Auth.Token != ""
- }
-
- func (cw *configWrapper) IsServiceConfigured() bool {
- return cw.config.Service.ReadTimeout > 0 &&
- cw.config.Service.WriteTimeout > 0 &&
- cw.config.Service.IdleTimeout > 0
-
- }
-
- var (
- instance IConfig
- once sync.Once
- initErr error
- )
-
- // GetConfig 获取配置单例实例
- func GetConfig() IConfig {
- once.Do(func() {
- config, err := loadConfig()
- if err != nil {
- initErr = err
- // 创建一个空的配置实例,避免nil指针
- 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)
-
- // 读取配置文件
- data, err := os.ReadFile(configFile)
- if err != nil {
- return nil, fmt.Errorf("failed to read config file %s: %v", configFile, err)
- }
-
- var config Config
- 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)
- }
|