118 lines
3.2 KiB
Go
118 lines
3.2 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/go-playground/validator/v10"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
// ConfigLoader định nghĩa interface để load cấu hình
|
|
type ConfigLoader interface {
|
|
Load() (*Config, error)
|
|
}
|
|
|
|
// ViperConfigLoader triển khai ConfigLoader với Viper
|
|
type ViperConfigLoader struct {
|
|
configPaths []string
|
|
configName string
|
|
configType string
|
|
envPrefix string
|
|
}
|
|
|
|
// NewConfigLoader tạo ConfigLoader mới với các giá trị mặc định
|
|
func NewConfigLoader() ConfigLoader {
|
|
return &ViperConfigLoader{
|
|
configPaths: []string{"./configs", ".", "./templates"},
|
|
configName: "config",
|
|
configType: "yaml",
|
|
envPrefix: "APP",
|
|
}
|
|
}
|
|
|
|
// Load đọc cấu hình từ file và biến môi trường
|
|
func (l *ViperConfigLoader) Load() (*Config, error) {
|
|
// Khởi tạo viper
|
|
v := viper.New()
|
|
|
|
// Thiết lập tên config và loại
|
|
v.SetConfigName(l.configName)
|
|
v.SetConfigType(l.configType)
|
|
|
|
// Thêm các paths để tìm config
|
|
for _, path := range l.configPaths {
|
|
v.AddConfigPath(path)
|
|
}
|
|
|
|
// Tự động đọc biến môi trường
|
|
v.AutomaticEnv()
|
|
v.SetEnvPrefix(l.envPrefix)
|
|
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
|
|
|
// Thiết lập giá trị mặc định
|
|
setDefaultValues(v)
|
|
|
|
// Đọc cấu hình
|
|
if err := v.ReadInConfig(); err != nil {
|
|
// Chỉ cảnh báo nếu không tìm thấy file, không gây lỗi
|
|
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
|
|
return nil, fmt.Errorf("error reading config file: %v", err)
|
|
}
|
|
}
|
|
|
|
// Set default logger level
|
|
if os.Getenv("LOG_LEVEL") == "" {
|
|
os.Setenv("LOG_LEVEL", "info")
|
|
}
|
|
|
|
// Bind cấu hình vào struct
|
|
var config Config
|
|
if err := v.Unmarshal(&config); err != nil {
|
|
return nil, fmt.Errorf("unable to decode config into struct: %v", err)
|
|
}
|
|
|
|
// Validate cấu hình
|
|
if err := validateConfig(&config); err != nil {
|
|
return nil, fmt.Errorf("config validation error: %v", err)
|
|
}
|
|
|
|
return &config, nil
|
|
}
|
|
|
|
// setDefaultValues thiết lập các giá trị mặc định cho config
|
|
func setDefaultValues(v *viper.Viper) {
|
|
// App defaults
|
|
v.SetDefault("app.name", "GoStarter")
|
|
v.SetDefault("app.version", "0.1.0")
|
|
v.SetDefault("app.environment", "development")
|
|
v.SetDefault("app.log_level", "info")
|
|
v.SetDefault("app.timezone", "UTC")
|
|
|
|
// Server defaults
|
|
v.SetDefault("server.host", "0.0.0.0")
|
|
v.SetDefault("server.port", 8080)
|
|
v.SetDefault("server.read_timeout", 15) // seconds
|
|
v.SetDefault("server.write_timeout", 15) // seconds
|
|
v.SetDefault("server.shutdown_timeout", 30) // seconds
|
|
v.SetDefault("server.trusted_proxies", []string{})
|
|
v.SetDefault("server.allow_origins", []string{"*"})
|
|
|
|
// Database defaults
|
|
v.SetDefault("database.driver", "postgres")
|
|
v.SetDefault("database.host", "localhost")
|
|
v.SetDefault("database.port", 5432)
|
|
v.SetDefault("database.max_open_conns", 25)
|
|
v.SetDefault("database.max_idle_conns", 5)
|
|
v.SetDefault("database.conn_max_lifetime", 300) // seconds
|
|
v.SetDefault("database.ssl_mode", "disable")
|
|
v.SetDefault("database.migration_path", "migrations")
|
|
}
|
|
|
|
// validateConfig xác thực cấu hình
|
|
func validateConfig(config *Config) error {
|
|
validate := validator.New()
|
|
return validate.Struct(config)
|
|
}
|