github.com/aaabigfish/gopkg@v1.1.0/config/config.go (about) 1 // Package config 提供最基础的配置加载功能 2 package config 3 4 import ( 5 "os" 6 "path/filepath" 7 "strings" 8 "time" 9 10 "github.com/fsnotify/fsnotify" 11 "github.com/spf13/cast" 12 "github.com/spf13/viper" 13 ) 14 15 const ( 16 EnvDev = "dev" 17 EnvTest = "test" 18 EnvMirror = "mirror" 19 EnvProd = "prod" 20 ) 21 22 // Get 查询配置/环境变量 23 var Get func(string) string 24 25 var ( 26 // Host 主机名 27 Host = "localhost" 28 // App 服务标识 29 App = "localapp" 30 // Env 运行环境 31 Env = EnvProd 32 // Zone 服务区域 33 Zone = "sh001" 34 35 DbMode = "release" 36 37 files = map[string]*Client{} 38 39 defaultFile = "config.toml" 40 41 configErr error 42 ) 43 44 type DBConfig struct { 45 Type string 46 Dsn string 47 MaxIdle int 48 MaxActive int 49 IdleTimeout int 50 } 51 52 // LogConfig is used to configure uber zap 53 type LogConfig struct { 54 Level string 55 FileName string 56 TimeFormat string 57 MaxSize int 58 MaxBackups int 59 MaxAge int 60 Compress bool 61 LocalTime bool 62 Console bool 63 } 64 65 func init() { 66 Host, _ = os.Hostname() 67 if appID := os.Getenv("APP_ID"); appID != "" { 68 App = appID 69 } 70 71 if env := os.Getenv("ENV"); env != "" { 72 Env = env 73 } 74 75 if zone := os.Getenv("ZONE"); zone != "" { 76 Zone = zone 77 } 78 79 if name := os.Getenv("CONF_NAME"); name != "" { 80 defaultFile = name 81 } 82 83 if dbmode := os.Getenv("DB_MODE"); dbmode != "" { 84 DbMode = dbmode 85 } 86 87 path := os.Getenv("CONF_PATH") 88 if path == "" { 89 var err error 90 path, err = os.Getwd() 91 if err != nil { 92 configErr = err 93 return 94 } 95 } 96 97 configPath := filepath.Join(path, "conf") 98 if !fileExists(configPath) { 99 appPath, err := filepath.Abs(filepath.Dir(os.Args[0])) 100 if err != nil { 101 configErr = err 102 return 103 } 104 configPath = filepath.Join(appPath, "conf") 105 } 106 107 fs, err := os.ReadDir(configPath) 108 if err != nil { 109 return 110 } 111 112 for _, f := range fs { 113 if !(strings.HasSuffix(f.Name(), ".toml") || strings.HasSuffix(f.Name(), ".json")) { 114 continue 115 } 116 117 v := viper.New() 118 v.SetConfigFile(filepath.Join(configPath, f.Name())) 119 if err := v.ReadInConfig(); err != nil { 120 configErr = err 121 return 122 } 123 v.AutomaticEnv() 124 125 files[f.Name()] = &Client{v} 126 } 127 128 if File(defaultFile) == nil { 129 return 130 } 131 132 Get = GetString 133 134 if appName := GetString("app.appname"); appName != "" { 135 App = appName 136 } 137 138 if env := GetString("app.env"); env != "" { 139 Env = env 140 } 141 142 if GetBool("log.Console") { 143 DbMode = "debug" 144 } 145 } 146 147 func Error() string { 148 return configErr.Error() 149 } 150 151 func NewDbConfig(key string) *DBConfig { 152 maxIdle := 10 153 maxActive := 1000 154 idleTimeout := 600 155 if v := GetInt("db_" + key + ".maxidle"); v > 0 { 156 maxIdle = v 157 } 158 if v := GetInt("db_" + key + ".maxactive"); v > 0 { 159 maxActive = v 160 } 161 if v := GetInt("db_" + key + ".idletimeout"); v > 0 { 162 idleTimeout = v 163 } 164 165 return &DBConfig{ 166 Type: GetString("db_" + key + ".type"), 167 Dsn: GetString("db_" + key + ".dsn"), 168 MaxIdle: maxIdle, 169 MaxActive: maxActive, 170 IdleTimeout: idleTimeout, 171 } 172 } 173 174 func NewLogConfig() *LogConfig { 175 cfg := &LogConfig{ 176 Level: "debug", 177 LocalTime: true, 178 Console: true, 179 } 180 181 if File(defaultFile) == nil { 182 return cfg 183 } 184 185 return &LogConfig{ 186 Level: GetString("log.Level"), 187 FileName: GetString("log.FileName"), 188 TimeFormat: GetString("log.TimeFormat"), 189 MaxSize: GetInt("log.MaxSize"), 190 MaxBackups: GetInt("log.MaxBackups"), 191 MaxAge: GetInt("log.MaxAge"), 192 Compress: GetBool("log.Compress"), 193 LocalTime: GetBool("log.LocalTime"), 194 Console: GetBool("log.Console"), 195 } 196 } 197 198 func fileExists(name string) bool { 199 if _, err := os.Stat(name); err != nil { 200 if os.IsNotExist(err) { 201 return false 202 } 203 } 204 return true 205 } 206 207 type Client struct { 208 *viper.Viper 209 } 210 211 // File 根据文件名获取对应配置对象 212 // 目前仅支持 toml和json 文件 213 // 如果要读取 foo.toml 配置,可以 File("foo.toml").Get("bar") 214 func File(name string) *Client { 215 return files[name] 216 } 217 218 // OnConfigChange 注册配置文件变更回调 219 // 需要在 WatchConfig 之前调用 220 func OnConfigChange(run func()) { 221 for _, v := range files { 222 v.OnConfigChange(func(in fsnotify.Event) { run() }) 223 } 224 } 225 226 // WatchConfig 启动配置变更监听,业务代码不要调用。 227 func WatchConfig() { 228 for _, v := range files { 229 v.WatchConfig() 230 } 231 } 232 233 // Set 设置配置,仅用于测试 234 func Set(key string, value interface{}) { File(defaultFile).Set(key, value) } 235 236 func GetBool(key string) bool { return File(defaultFile).GetBool(key) } 237 func GetDuration(key string) time.Duration { return File(defaultFile).GetDuration(key) } 238 func GetFloat64(key string) float64 { return File(defaultFile).GetFloat64(key) } 239 func GetInt(key string) int { return File(defaultFile).GetInt(key) } 240 func GetInt32(key string) int32 { return File(defaultFile).GetInt32(key) } 241 func GetInt64(key string) int64 { return File(defaultFile).GetInt64(key) } 242 func GetIntSlice(key string) []int { return File(defaultFile).GetIntSlice(key) } 243 func GetSizeInBytes(key string) uint { return File(defaultFile).GetSizeInBytes(key) } 244 func GetString(key string) string { return File(defaultFile).GetString(key) } 245 func GetStringSlice(key string) []string { return File(defaultFile).GetStringSlice(key) } 246 func GetTime(key string) time.Time { return File(defaultFile).GetTime(key) } 247 func GetUint(key string) uint { return File(defaultFile).GetUint(key) } 248 func GetUint32(key string) uint32 { return File(defaultFile).GetUint32(key) } 249 func GetUint64(key string) uint64 { return File(defaultFile).GetUint64(key) } 250 251 func GetStringMap(key string) map[string]interface{} { return File(defaultFile).GetStringMap(key) } 252 253 func GetStringMapInt(key string) map[string]int { 254 stringMap := File(defaultFile).GetStringMap(key) 255 mapInt := make(map[string]int, len(stringMap)) 256 for key, val := range stringMap { 257 mapInt[key] = cast.ToInt(val) 258 } 259 return mapInt 260 } 261 262 func GetStringMapString(key string) map[string]string { 263 return File(defaultFile).GetStringMapString(key) 264 } 265 func GetStringMapStringSlice(key string) map[string][]string { 266 return File(defaultFile).GetStringMapStringSlice(key) 267 }