-
Notifications
You must be signed in to change notification settings - Fork 0
/
props.go
153 lines (123 loc) · 3.87 KB
/
props.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
143
144
145
146
147
148
149
150
151
152
153
package props
import (
"strconv"
"sort"
)
// Source 定义了配置数据来源.
// 一个数据来源必须提供一个 Find 方法用于支持从该来源读取配置数据
type Source interface {
Find(key string) (string, bool)
}
// Props 定义了配置数据的操作集合.
// 该接口提供了添加配置数据源,配置项查找,配置项读取,使用配置项扩展变量等多个函数.
type Props interface {
// Add 用于将配置数据源 s,以优先级 priority,添加到 Props 对象中去.
Add(priority uint8, s Source) Source
// Find 函数尝试从多个配置数据源查找名字为 key 的配置项.
// 如果能够找到返回找到的配置项的值和true;否则,第二个返回值为false。
// 如果多个配置数据源都存在名字为 key 的配置项,那么以优先级最高的配置项为准。
// String、Int64、Uint64、Bool 等函数是对 Find 函数的简单封装。
Find(key string) (string, bool)
// String 尝试将找到的配置项以 string 的形式返回,如果找不到就返回 def.
String(key string, def string) string
// Int64 尝试将找到的配置项转换为 int64 的形式,如果找不到或者转换失败,就返回 def.
Int64(key string, def int64) int64
// Uint64 尝试将找到的配置项转换为 uint64 的形式,如果找不到或者转换失败,就返回 def.
Uint64(key string, def uint64) uint64
// Bool 尝试将找到的配置项转换为 bool 的形式,如果找不到或者转换失败,就返回 def.
// 当前支持的数据映射方式为:
// "1", "t", "T", "true", "TRUE", "True" 会被映射为 true;
// "0", "f", "F", "false", "FALSE", "False" 会被映射为 false。
// 如果配置项的值为其他的值,作为转换失败处理。
Bool(key string, def bool) bool
// 将字符串 s 中的所有 ${key} 形式的可扩展变量,替换为本 Props 对象内部的配置项 key 的值,并最终返回替换后的结果.
// 如果某个 key 的配置项在 Props 对象中不存在,将原样保留 ${key};
// 如果某个 key 的配置项的值里面还含有 ${xxx},那么也会自动展开;
// 如果变量存在循环引用现象,返回失败;
Expand(s string) (string, error)
}
// NewProps 用于创建一个新的 Props 对象.
func NewProps() Props {
return &implProps{
items: make([]*implSourceItem, 0, 5),
}
}
type implSourceItem struct {
priority int
source Source
next *implSourceItem
}
type implProps struct {
items []*implSourceItem
}
func (p *implProps) Add(priority uint8, s Source) Source {
newItem := &implSourceItem{
priority: int(priority),
source: s,
next: nil,
}
for i := 0; i < len(p.items); i++ {
if int(priority) == p.items[i].priority {
newItem.next = p.items[i]
p.items[i] = newItem
return s
}
}
p.items = append(p.items, newItem)
sort.Slice(p.items, func(i, j int) bool {
return p.items[i].priority < p.items[j].priority
})
return s
}
func (p implProps) Find(key string) (string, bool) {
for i := len(p.items) - 1; i >= 0; i-- {
val, ok := p.items[i].source.Find(key)
if ok {
return val, true
}
}
return "", false
}
func (p implProps) String(key string, def string) string {
val, ok := p.Find(key)
if !ok {
return def
}
return val
}
func (p implProps) Int64(key string, def int64) int64 {
val, ok := p.Find(key)
if !ok {
return def
}
i, err := strconv.ParseInt(val, 0, 64)
if nil != err {
return def
}
return i
}
func (p implProps) Uint64(key string, def uint64) uint64 {
val, ok := p.Find(key)
if !ok {
return def
}
i, err := strconv.ParseUint(val, 0, 64)
if nil != err {
return def
}
return i
}
func (p implProps) Bool(key string, def bool) bool {
val, ok := p.Find(key)
if !ok {
return def
}
i, err := strconv.ParseBool(val)
if nil != err {
return def
}
return i
}
func (p implProps) Expand(s string) (string, error) {
return s, nil
}