-
Notifications
You must be signed in to change notification settings - Fork 0
/
configor.go
142 lines (119 loc) · 3.5 KB
/
configor.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package configor
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path"
"reflect"
"regexp"
"strings"
"time"
)
type Configor struct {
*Config
configModTimes map[string]time.Time
}
type Config struct {
Environment string
ENVPrefix string
Debug bool
Verbose bool
Silent bool
AutoReload bool
AutoReloadInterval time.Duration
AutoReloadCallback func(config interface{})
// In case of json files, this field will be used only when compiled with
// go 1.10 or later.
// This field will be ignored when compiled with go versions lower than 1.10.
ErrorOnUnmatchedKeys bool
}
// New initialize a Configor
func New(config *Config) *Configor {
if config == nil {
config = &Config{}
}
if os.Getenv("CONFIGOR_DEBUG_MODE") != "" {
config.Debug = true
}
if os.Getenv("CONFIGOR_VERBOSE_MODE") != "" {
config.Verbose = true
}
if os.Getenv("CONFIGOR_SILENT_MODE") != "" {
config.Silent = true
}
if config.AutoReload && config.AutoReloadInterval == 0 {
config.AutoReloadInterval = time.Second
}
return &Configor{Config: config}
}
var testRegexp = regexp.MustCompile("_test|(\\.test$)")
// GetEnvironment get environment
func (configor *Configor) GetEnvironment() string {
if configor.Environment == "" {
if env := os.Getenv("CONFIGOR_ENV"); env != "" {
return env
}
if testRegexp.MatchString(os.Args[0]) {
return "test"
}
return "development"
}
return configor.Environment
}
// GetErrorOnUnmatchedKeys returns a boolean indicating if an error should be
// thrown if there are keys in the config file that do not correspond to the
// config struct
func (configor *Configor) GetErrorOnUnmatchedKeys() bool {
return configor.ErrorOnUnmatchedKeys
}
// Load will unmarshal configurations to struct from files that you provide
func (configor *Configor) Load(config interface{}, files ...string) (err error) {
////////配置样本文件不存在,创建配置样本
fileSuffix := path.Ext(files[0])
filenameOnly := strings.TrimSuffix(files[0], fileSuffix)
examplefile := filenameOnly + ".example" + fileSuffix
if !FileIsExist(examplefile) {
tmpCnf := config
configor.processTags(tmpCnf)
data, _ := json.Marshal(&tmpCnf)
var str bytes.Buffer
_ = json.Indent(&str, []byte(data), "", " ")
ioutil.WriteFile(examplefile, str.Bytes(), 0644)
}
/////////////
defaultValue := reflect.Indirect(reflect.ValueOf(config))
if !defaultValue.CanAddr() {
return fmt.Errorf("Config %v should be addressable", config)
}
err, _ = configor.load(config, false, files...)
if configor.Config.AutoReload {
go func() {
timer := time.NewTimer(configor.Config.AutoReloadInterval)
for range timer.C {
reflectPtr := reflect.New(reflect.ValueOf(config).Elem().Type())
reflectPtr.Elem().Set(defaultValue)
var changed bool
if err, changed = configor.load(reflectPtr.Interface(), true, files...); err == nil && changed {
reflect.ValueOf(config).Elem().Set(reflectPtr.Elem())
if configor.Config.AutoReloadCallback != nil {
configor.Config.AutoReloadCallback(config)
}
} else if err != nil {
fmt.Printf("Failed to reload configuration from %v, got error %v\n", files, err)
}
timer.Reset(configor.Config.AutoReloadInterval)
}
}()
}
return
}
// ENV return environment
func ENV() string {
return New(nil).GetEnvironment()
}
// Load will unmarshal configurations to struct from files that you provide
func Load(config interface{}, files ...string) error {
return New(nil).Load(config, files...)
}