Skip to content

Commit 7dd11b0

Browse files
committed
支持配置文件标签别名
1 parent df03f14 commit 7dd11b0

File tree

2 files changed

+136
-82
lines changed

2 files changed

+136
-82
lines changed

config/config.go

Lines changed: 126 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,19 @@ func configSplit(raw, sep string) []string {
2929
}
3030

3131
//NewConfig 加载配置文件.
32-
func NewConfig(path string) (c *Config, err error) {
33-
dat, err := ioutil.ReadFile(path)
34-
if err != nil {
35-
return nil, err
32+
func NewConfig(path, body string) (c *Config, err error) {
33+
if path != "" {
34+
dat, err := ioutil.ReadFile(path)
35+
if err != nil {
36+
return nil, err
37+
}
38+
body = string(dat)
3639
}
3740

3841
c = &Config{kv: make(map[string]string)}
3942
s := ""
4043

41-
for _, line := range strings.Split(string(dat), "\n") {
44+
for _, line := range strings.Split(body, "\n") {
4245
line = strings.TrimSpace(line)
4346
if len(line) < 3 || line[0] == ';' || line[0] == '#' {
4447
continue
@@ -78,8 +81,7 @@ func (c *Config) GetData(s, k string, result interface{}, d interface{}) error {
7881
if !ok {
7982
//没有对应的key, 这时候要看看有没有default.
8083
if d == nil {
81-
fmt.Printf("kv:%#v, key:%v\n", c.kv, key)
82-
return errors.Annotatef(ErrNotFound, "%v:%v", s, k)
84+
return errors.Annotatef(ErrNotFound, "%v->%v", s, k)
8385
}
8486
rv.Set(reflect.ValueOf(d))
8587
return nil
@@ -121,13 +123,98 @@ func (c *Config) GetData(s, k string, result interface{}, d interface{}) error {
121123
return nil
122124
}
123125

126+
//ParseConfig 解析内存中配置文件.
127+
func ParseConfig(body string, result interface{}) error {
128+
c, err := NewConfig("", body)
129+
if err != nil {
130+
return errors.Trace(err)
131+
}
132+
return c.Parse(result)
133+
}
134+
124135
//LoadConfig 加载文件形式配置文件, 并解析成指定结构.
125136
func LoadConfig(path string, result interface{}) error {
126-
c, err := NewConfig(path)
137+
c, err := NewConfig(path, "")
127138
if err != nil {
128139
return errors.Trace(err)
129140
}
141+
return c.Parse(result)
142+
}
130143

144+
func (c Config) getDefault(k reflect.Kind, v string) (interface{}, error) {
145+
switch k {
146+
case reflect.Uint:
147+
d, err := strconv.ParseUint(v, 10, 64)
148+
if err != nil {
149+
return nil, errors.Trace(err)
150+
}
151+
return uint(d), nil
152+
case reflect.Uint8:
153+
d, err := strconv.ParseUint(v, 10, 64)
154+
if err != nil {
155+
return nil, errors.Trace(err)
156+
}
157+
return uint8(d), nil
158+
case reflect.Uint16:
159+
d, err := strconv.ParseUint(v, 10, 64)
160+
if err != nil {
161+
return nil, errors.Trace(err)
162+
}
163+
return uint16(d), nil
164+
case reflect.Uint32:
165+
d, err := strconv.ParseUint(v, 10, 64)
166+
if err != nil {
167+
return nil, errors.Trace(err)
168+
}
169+
return uint32(d), nil
170+
case reflect.Uint64:
171+
return strconv.ParseUint(v, 10, 64)
172+
case reflect.Int:
173+
d, err := strconv.ParseInt(v, 10, 64)
174+
if err != nil {
175+
return nil, errors.Trace(err)
176+
}
177+
return int(d), nil
178+
case reflect.Int8:
179+
d, err := strconv.ParseInt(v, 10, 64)
180+
if err != nil {
181+
return nil, errors.Trace(err)
182+
}
183+
return uint8(d), nil
184+
case reflect.Int16:
185+
d, err := strconv.ParseInt(v, 10, 64)
186+
if err != nil {
187+
return nil, errors.Trace(err)
188+
}
189+
return uint16(d), nil
190+
case reflect.Int32:
191+
d, err := strconv.ParseInt(v, 10, 64)
192+
if err != nil {
193+
return nil, errors.Trace(err)
194+
}
195+
return uint32(d), nil
196+
case reflect.Int64:
197+
return strconv.ParseInt(v, 10, 64)
198+
case reflect.String:
199+
return v, nil
200+
case reflect.Bool:
201+
return strconv.ParseBool(v)
202+
case reflect.Float32:
203+
d, err := strconv.ParseFloat(v, 32)
204+
if err != nil {
205+
return nil, errors.Trace(err)
206+
}
207+
return float32(d), nil
208+
case reflect.Float64:
209+
return strconv.ParseFloat(v, 32)
210+
211+
default:
212+
return nil, Errunsupported
213+
}
214+
}
215+
216+
//Parse 根据result结构读配置文件.
217+
func (c *Config) Parse(result interface{}) error {
131218
rt := reflect.TypeOf(result)
132219
rv := reflect.ValueOf(result)
133220

@@ -154,67 +241,42 @@ func LoadConfig(path string, result interface{}) error {
154241
ft = ft.Elem()
155242
}
156243

157-
if ft.Kind() == reflect.Struct {
158-
for j := 0; j < ft.NumField(); j++ {
159-
sf := ft.Field(j)
160-
if f.PkgPath != "" && !f.Anonymous { // unexported
161-
continue
162-
}
163-
sfv := fv.Field(j)
164-
if sf.Type.Kind() == reflect.Ptr {
165-
sfv = reflect.New(sfv.Elem().Type())
166-
fv.Field(j).Set(sfv)
167-
}
244+
if ft.Kind() != reflect.Struct {
245+
continue
246+
}
168247

169-
var d interface{}
170-
if v := sf.Tag.Get("default"); v != "" {
171-
switch sf.Type.Kind() {
172-
case reflect.Uint:
173-
d, err = strconv.ParseUint(v, 10, 64)
174-
d = uint(d.(uint64))
175-
case reflect.Uint8:
176-
d, err = strconv.ParseUint(v, 10, 64)
177-
d = uint8(d.(uint64))
178-
case reflect.Uint16:
179-
d, err = strconv.ParseUint(v, 10, 64)
180-
d = uint16(d.(uint64))
181-
case reflect.Uint32:
182-
d, err = strconv.ParseUint(v, 10, 64)
183-
d = uint32(d.(uint64))
184-
case reflect.Uint64:
185-
d, err = strconv.ParseUint(v, 10, 64)
186-
case reflect.Int:
187-
d, err = strconv.ParseInt(v, 10, 64)
188-
d = int(d.(int64))
189-
case reflect.Int8:
190-
d, err = strconv.ParseInt(v, 10, 64)
191-
d = uint8(d.(uint64))
192-
case reflect.Int16:
193-
d, err = strconv.ParseInt(v, 10, 64)
194-
d = uint16(d.(uint64))
195-
case reflect.Int32:
196-
d, err = strconv.ParseInt(v, 10, 64)
197-
d = uint32(d.(uint64))
198-
case reflect.Int64:
199-
d, err = strconv.ParseInt(v, 10, 64)
200-
case reflect.String:
201-
d = v
202-
case reflect.Bool:
203-
d, err = strconv.ParseBool(v)
204-
case reflect.Float32, reflect.Float64:
205-
d, err = strconv.ParseFloat(v, 32)
206-
207-
default:
208-
return Errunsupported
209-
}
210-
}
248+
segment := f.Name
249+
if name := f.Tag.Get("cfg_key"); name != "" {
250+
segment = name
251+
}
252+
253+
for j := 0; j < ft.NumField(); j++ {
254+
sf := ft.Field(j)
255+
if f.PkgPath != "" && !f.Anonymous { // unexported
256+
continue
257+
}
258+
sfv := fv.Field(j)
259+
if sf.Type.Kind() == reflect.Ptr {
260+
sfv = reflect.New(sfv.Elem().Type())
261+
fv.Field(j).Set(sfv)
262+
}
263+
264+
var cfgDefault interface{}
265+
if v := sf.Tag.Get("cfg_default"); v != "" {
266+
d, err := c.getDefault(sf.Type.Kind(), v)
211267
if err != nil {
212268
return errors.Trace(err)
213269
}
270+
cfgDefault = d
271+
}
214272

215-
if err = c.GetData(f.Name, sf.Name, sfv.Addr().Interface(), d); err != nil {
216-
return errors.Trace(err)
217-
}
273+
key := sf.Name
274+
if name := sf.Tag.Get("cfg_key"); name != "" {
275+
key = name
276+
}
277+
278+
if err := c.GetData(segment, key, sfv.Addr().Interface(), cfgDefault); err != nil {
279+
return errors.Trace(err)
218280
}
219281
}
220282
}

config/config_test.go

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package config
22

33
import (
4-
"io/ioutil"
54
"os"
65
"testing"
76

@@ -10,32 +9,25 @@ import (
109

1110
var (
1211
c *Config
13-
path string
14-
)
15-
16-
func TestMain(main *testing.M) {
17-
data := `
12+
data = `
1813
[db]
1914
domain =mailchina.org
20-
enable=true
15+
db_enable=true
2116
# test comments
2217
;port=3306
2318
[api]
2419
url=http://baiud.com/
2520
enable=T
2621
headersize=123
2722
`
28-
f, err := ioutil.TempFile("/tmp/", "test_config_")
29-
if err != nil {
30-
panic(err.Error())
31-
}
32-
f.WriteString(data)
33-
path = f.Name()
34-
f.Close()
23+
)
3524

36-
if c, err = NewConfig(path); err != nil {
25+
func TestMain(main *testing.M) {
26+
nc, err := NewConfig("", data)
27+
if err != nil {
3728
panic(err.Error())
3829
}
30+
c = nc
3931

4032
os.Exit(main.Run())
4133
}
@@ -67,8 +59,8 @@ func TestConfigBool(t *testing.T) {
6759
type testConf struct {
6860
DB struct {
6961
Domain string
70-
Port int `default:"9088"`
71-
Enable bool
62+
Port int `cfg_default:"9088"`
63+
Enable bool `cfg_key:"db_enable"`
7264
}
7365

7466
API struct {
@@ -80,7 +72,7 @@ type testConf struct {
8072

8173
func TestConfigStruct(t *testing.T) {
8274
var conf testConf
83-
if err := LoadConfig(path, &conf); err != nil {
75+
if err := ParseConfig(data, &conf); err != nil {
8476
t.Fatalf(errors.ErrorStack(err))
8577
}
8678
t.Logf("conf:%+v", conf)

0 commit comments

Comments
 (0)