|
|
package database
|
|
|
|
|
|
import (
|
|
|
"encoding/json"
|
|
|
"fmt"
|
|
|
"github.com/go-kratos/kratos/v2/log"
|
|
|
"gopkg.in/yaml.v3"
|
|
|
"os"
|
|
|
"strings"
|
|
|
"sync"
|
|
|
)
|
|
|
|
|
|
var (
|
|
|
configData map[string]interface{}
|
|
|
loadOnce sync.Once
|
|
|
loadErr error
|
|
|
configPath string
|
|
|
)
|
|
|
|
|
|
// InitConfigPath 设置配置路径(可选)
|
|
|
func InitConfigPath(path string) {
|
|
|
configPath = path
|
|
|
}
|
|
|
|
|
|
// loadYAML 加载 YAML 到 map
|
|
|
func loadYAML(filePath string) (map[string]interface{}, error) {
|
|
|
yamlFile, err := os.ReadFile(filePath)
|
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("failed to read config file: %v", err)
|
|
|
}
|
|
|
|
|
|
var raw map[string]interface{}
|
|
|
err = yaml.Unmarshal(yamlFile, &raw)
|
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("failed to unmarshal yaml: %v", err)
|
|
|
}
|
|
|
|
|
|
b, _ := json.MarshalIndent(raw, "", " ")
|
|
|
log.Info("loadYAML: ", string(b))
|
|
|
converted, ok := toStringKeyMap(raw).(map[string]interface{})
|
|
|
if !ok {
|
|
|
return nil, fmt.Errorf("failed to convert config to map[string]interface{}")
|
|
|
}
|
|
|
|
|
|
return converted, nil
|
|
|
}
|
|
|
|
|
|
// GetConfig 获取全局配置 map,只加载一次
|
|
|
func GetConfig() (map[string]interface{}, error) {
|
|
|
loadOnce.Do(func() {
|
|
|
if configPath == "" {
|
|
|
configPath = "config.yaml"
|
|
|
}
|
|
|
configData, loadErr = loadYAML(configPath)
|
|
|
})
|
|
|
return configData, loadErr
|
|
|
}
|
|
|
|
|
|
// Get 获取嵌套配置,例如 Get("database.driver")
|
|
|
func Get(key string) (interface{}, error) {
|
|
|
cfg, err := GetConfig()
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
|
|
|
keys := strings.Split(key, ".")
|
|
|
var val interface{} = cfg
|
|
|
|
|
|
for _, k := range keys {
|
|
|
m, ok := val.(map[string]interface{})
|
|
|
if !ok {
|
|
|
return nil, fmt.Errorf("invalid path: %s", key)
|
|
|
}
|
|
|
val, ok = m[k]
|
|
|
if !ok {
|
|
|
return nil, fmt.Errorf("key not found: %s", key)
|
|
|
}
|
|
|
}
|
|
|
return val, nil
|
|
|
}
|
|
|
|
|
|
func toStringKeyMap(i interface{}) interface{} {
|
|
|
switch x := i.(type) {
|
|
|
case map[interface{}]interface{}:
|
|
|
m2 := map[string]interface{}{}
|
|
|
for k, v := range x {
|
|
|
keyStr := fmt.Sprintf("%v", k)
|
|
|
m2[keyStr] = toStringKeyMap(v)
|
|
|
}
|
|
|
return m2
|
|
|
case []interface{}:
|
|
|
for i, v := range x {
|
|
|
x[i] = toStringKeyMap(v)
|
|
|
}
|
|
|
}
|
|
|
return i
|
|
|
}
|