package config import ( "bytes" "fmt" "net" "os" "time" "gopkg.in/yaml.v3" ) const DefaultPath = "config/local.yaml" // Config 汇总用户服务的运行配置。 type Config struct { App AppConfig `yaml:"app"` Registry RegistryConfig `yaml:"registry"` } // AppConfig 描述用户服务自身监听参数。 type AppConfig struct { Name string `yaml:"name"` Env string `yaml:"env"` HTTPAddr string `yaml:"http_addr"` GRPCAddr string `yaml:"grpc_addr"` ShutdownTimeout time.Duration `yaml:"shutdown_timeout"` } // RegistryConfig 预留服务注册中心接入参数,当前只保留注销钩子扩展点。 type RegistryConfig struct { Enabled bool `yaml:"enabled"` Provider string `yaml:"provider"` Endpoint string `yaml:"endpoint"` ServiceName string `yaml:"service_name"` InstanceID string `yaml:"instance_id"` RegisterTimeout time.Duration `yaml:"register_timeout"` DeregisterTimeout time.Duration `yaml:"deregister_timeout"` } // Load 从 YAML 文件加载配置并校验。 func Load(path string) (Config, error) { data, err := os.ReadFile(path) if err != nil { return Config{}, fmt.Errorf("read config file %s: %w", path, err) } cfg := defaultConfig() decoder := yaml.NewDecoder(bytes.NewReader(data)) decoder.KnownFields(true) if err := decoder.Decode(&cfg); err != nil { return Config{}, fmt.Errorf("decode config file %s: %w", path, err) } if err := validate(cfg); err != nil { return Config{}, err } return cfg, nil } func defaultConfig() Config { return Config{ App: AppConfig{ Name: "chatappuser", Env: "local", HTTPAddr: ":8081", GRPCAddr: ":9001", ShutdownTimeout: 10 * time.Second, }, Registry: RegistryConfig{ RegisterTimeout: 3 * time.Second, DeregisterTimeout: 5 * time.Second, }, } } func validate(cfg Config) error { if cfg.App.Name == "" { return fmt.Errorf("app.name is required") } if _, err := net.ResolveTCPAddr("tcp", cfg.App.HTTPAddr); err != nil { return fmt.Errorf("app.http_addr is invalid: %w", err) } if _, err := net.ResolveTCPAddr("tcp", cfg.App.GRPCAddr); err != nil { return fmt.Errorf("app.grpc_addr is invalid: %w", err) } if cfg.App.ShutdownTimeout <= 0 { return fmt.Errorf("app.shutdown_timeout must be greater than 0") } if cfg.Registry.RegisterTimeout <= 0 { return fmt.Errorf("registry.register_timeout must be greater than 0") } if cfg.Registry.DeregisterTimeout <= 0 { return fmt.Errorf("registry.deregister_timeout must be greater than 0") } return nil }