Init commit.
Add: simple project structure for `mygo.server`. Add: README files.
This commit is contained in:
3
mygo.server/internal/app/version.go
Normal file
3
mygo.server/internal/app/version.go
Normal file
@ -0,0 +1,3 @@
|
||||
package app
|
||||
|
||||
const Version = "0.0.1"
|
117
mygo.server/internal/config/config.go
Normal file
117
mygo.server/internal/config/config.go
Normal file
@ -0,0 +1,117 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type ServerConfig struct {
|
||||
Server struct {
|
||||
Listen string `mapstructure:"listen"`
|
||||
Port string `mapstructure:"port"`
|
||||
} `mapstructure:"server"`
|
||||
|
||||
Database struct {
|
||||
Type string `mapstructure:"type"`
|
||||
Host string `mapstructure:"host"`
|
||||
// Port int `mapstructure:"port"`
|
||||
// User string `mapstructure:"user"`
|
||||
} `mapstructure:"database"`
|
||||
|
||||
Auth struct {
|
||||
JWTSecret string `mapstructure:"jwt_secret"`
|
||||
} `mapstructure:"auth"`
|
||||
|
||||
Storage struct {
|
||||
Type string `mapstructure:"type"`
|
||||
Local struct {
|
||||
RootDir string `mapstructure:"root_dir"`
|
||||
} `mapstructure:"local"`
|
||||
S3 struct {
|
||||
Endpoint string `mapstructure:"endpoint"`
|
||||
Bucket string `mapstructure:"bucket"`
|
||||
} `mapstructure:"s3"`
|
||||
} `mapstructure:"storage"`
|
||||
}
|
||||
|
||||
func setDefaultConfig(v *viper.Viper) {
|
||||
|
||||
}
|
||||
|
||||
// Bind Environment Variables to config
|
||||
func bindEnvVariables(v *viper.Viper) {
|
||||
// 设置环境变量前缀
|
||||
v.SetEnvPrefix("MYGO")
|
||||
|
||||
// 使viper能够从环境变量读取配置
|
||||
v.AutomaticEnv()
|
||||
|
||||
// 将环境变量中的下划线转换为点,如MYGO_SERVER_PORT对应server.port
|
||||
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
||||
|
||||
// 明确绑定特定环境变量
|
||||
// v.BindEnv("server.host", "MYGO_SERVER_HOST")
|
||||
// v.BindEnv("server.port", "MYGO_SERVER_PORT")
|
||||
// v.BindEnv("database.host", "MYGO_DB_HOST")
|
||||
// v.BindEnv("database.port", "MYGO_DB_PORT")
|
||||
// v.BindEnv("database.user", "MYGO_DB_USER")
|
||||
// v.BindEnv("database.password", "MYGO_DB_PASSWORD")
|
||||
}
|
||||
|
||||
// parseConfig unmarshals viper config into ServerConfig
|
||||
func parseConfig(v *viper.Viper) (*ServerConfig, error) {
|
||||
config := &ServerConfig{}
|
||||
if err := v.Unmarshal(config); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse config: %w", err)
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// Load config file
|
||||
func loadConfigFile(v *viper.Viper, configPath string) (*ServerConfig, error) {
|
||||
v.SetConfigType("yaml")
|
||||
|
||||
if configPath != "" {
|
||||
v.SetConfigFile(configPath)
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
return nil, fmt.Errorf("failed to load config file %s: %w", configPath, err)
|
||||
}
|
||||
return parseConfig(v)
|
||||
}
|
||||
|
||||
v.SetConfigName("config")
|
||||
configPaths := []string{".", "./config"}
|
||||
for _, path := range configPaths {
|
||||
v.AddConfigPath(path)
|
||||
}
|
||||
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
|
||||
return nil, nil // No config file found is not an error
|
||||
}
|
||||
return nil, fmt.Errorf("config file read error: %w", err)
|
||||
}
|
||||
return parseConfig(v)
|
||||
}
|
||||
|
||||
// LoadConfig is the main entry point for configuration loading
|
||||
func LoadConfig(configPath string) (*ServerConfig, error) {
|
||||
v := viper.New()
|
||||
setDefaultConfig(v)
|
||||
|
||||
fileConfig, err := loadConfigFile(v, configPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if fileConfig != nil {
|
||||
fmt.Printf("Loaded config from %s\n", v.ConfigFileUsed())
|
||||
} else {
|
||||
fmt.Println("Using default configuration (no config file found)")
|
||||
}
|
||||
|
||||
bindEnvVariables(v)
|
||||
return parseConfig(v)
|
||||
}
|
Reference in New Issue
Block a user