1
0

config.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // Copyright 2014 beego Author. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Package config is used to parse config.
  15. // Usage:
  16. // import "github.com/astaxie/beego/config"
  17. //Examples.
  18. //
  19. // cnf, err := config.NewConfig("ini", "config.conf")
  20. //
  21. // cnf APIS:
  22. //
  23. // cnf.Set(key, val string) error
  24. // cnf.String(key string) string
  25. // cnf.Strings(key string) []string
  26. // cnf.Int(key string) (int, error)
  27. // cnf.Int64(key string) (int64, error)
  28. // cnf.Bool(key string) (bool, error)
  29. // cnf.Float(key string) (float64, error)
  30. // cnf.DefaultString(key string, defaultVal string) string
  31. // cnf.DefaultStrings(key string, defaultVal []string) []string
  32. // cnf.DefaultInt(key string, defaultVal int) int
  33. // cnf.DefaultInt64(key string, defaultVal int64) int64
  34. // cnf.DefaultBool(key string, defaultVal bool) bool
  35. // cnf.DefaultFloat(key string, defaultVal float64) float64
  36. // cnf.DIY(key string) (interface{}, error)
  37. // cnf.GetSection(section string) (map[string]string, error)
  38. // cnf.SaveConfigFile(filename string) error
  39. //More docs http://beego.me/docs/module/config.md
  40. package config
  41. import (
  42. "fmt"
  43. "os"
  44. "reflect"
  45. "time"
  46. )
  47. // Configer defines how to get and set value from configuration raw data.
  48. type Configer interface {
  49. Set(key, val string) error //support section::key type in given key when using ini type.
  50. String(key string) string //support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
  51. Strings(key string) []string //get string slice
  52. Int(key string) (int, error)
  53. Int64(key string) (int64, error)
  54. Bool(key string) (bool, error)
  55. Float(key string) (float64, error)
  56. DefaultString(key string, defaultVal string) string // support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
  57. DefaultStrings(key string, defaultVal []string) []string //get string slice
  58. DefaultInt(key string, defaultVal int) int
  59. DefaultInt64(key string, defaultVal int64) int64
  60. DefaultBool(key string, defaultVal bool) bool
  61. DefaultFloat(key string, defaultVal float64) float64
  62. DIY(key string) (interface{}, error)
  63. GetSection(section string) (map[string]string, error)
  64. SaveConfigFile(filename string) error
  65. }
  66. // Config is the adapter interface for parsing config file to get raw data to Configer.
  67. type Config interface {
  68. Parse(key string) (Configer, error)
  69. ParseData(data []byte) (Configer, error)
  70. }
  71. var adapters = make(map[string]Config)
  72. // Register makes a config adapter available by the adapter name.
  73. // If Register is called twice with the same name or if driver is nil,
  74. // it panics.
  75. func Register(name string, adapter Config) {
  76. if adapter == nil {
  77. panic("config: Register adapter is nil")
  78. }
  79. if _, ok := adapters[name]; ok {
  80. panic("config: Register called twice for adapter " + name)
  81. }
  82. adapters[name] = adapter
  83. }
  84. // NewConfig adapterName is ini/json/xml/yaml.
  85. // filename is the config file path.
  86. func NewConfig(adapterName, filename string) (Configer, error) {
  87. adapter, ok := adapters[adapterName]
  88. if !ok {
  89. return nil, fmt.Errorf("config: unknown adaptername %q (forgotten import?)", adapterName)
  90. }
  91. return adapter.Parse(filename)
  92. }
  93. // NewConfigData adapterName is ini/json/xml/yaml.
  94. // data is the config data.
  95. func NewConfigData(adapterName string, data []byte) (Configer, error) {
  96. adapter, ok := adapters[adapterName]
  97. if !ok {
  98. return nil, fmt.Errorf("config: unknown adaptername %q (forgotten import?)", adapterName)
  99. }
  100. return adapter.ParseData(data)
  101. }
  102. // ExpandValueEnvForMap convert all string value with environment variable.
  103. func ExpandValueEnvForMap(m map[string]interface{}) map[string]interface{} {
  104. for k, v := range m {
  105. switch value := v.(type) {
  106. case string:
  107. m[k] = ExpandValueEnv(value)
  108. case map[string]interface{}:
  109. m[k] = ExpandValueEnvForMap(value)
  110. case map[string]string:
  111. for k2, v2 := range value {
  112. value[k2] = ExpandValueEnv(v2)
  113. }
  114. m[k] = value
  115. }
  116. }
  117. return m
  118. }
  119. // ExpandValueEnv returns value of convert with environment variable.
  120. //
  121. // Return environment variable if value start with "${" and end with "}".
  122. // Return default value if environment variable is empty or not exist.
  123. //
  124. // It accept value formats "${env}" , "${env||}}" , "${env||defaultValue}" , "defaultvalue".
  125. // Examples:
  126. // v1 := config.ExpandValueEnv("${GOPATH}") // return the GOPATH environment variable.
  127. // v2 := config.ExpandValueEnv("${GOAsta||/usr/local/go}") // return the default value "/usr/local/go/".
  128. // v3 := config.ExpandValueEnv("Astaxie") // return the value "Astaxie".
  129. func ExpandValueEnv(value string) (realValue string) {
  130. realValue = value
  131. vLen := len(value)
  132. // 3 = ${}
  133. if vLen < 3 {
  134. return
  135. }
  136. // Need start with "${" and end with "}", then return.
  137. if value[0] != '$' || value[1] != '{' || value[vLen-1] != '}' {
  138. return
  139. }
  140. key := ""
  141. defalutV := ""
  142. // value start with "${"
  143. for i := 2; i < vLen; i++ {
  144. if value[i] == '|' && (i+1 < vLen && value[i+1] == '|') {
  145. key = value[2:i]
  146. defalutV = value[i+2 : vLen-1] // other string is default value.
  147. break
  148. } else if value[i] == '}' {
  149. key = value[2:i]
  150. break
  151. }
  152. }
  153. realValue = os.Getenv(key)
  154. if realValue == "" {
  155. realValue = defalutV
  156. }
  157. return
  158. }
  159. // ParseBool returns the boolean value represented by the string.
  160. //
  161. // It accepts 1, 1.0, t, T, TRUE, true, True, YES, yes, Yes,Y, y, ON, on, On,
  162. // 0, 0.0, f, F, FALSE, false, False, NO, no, No, N,n, OFF, off, Off.
  163. // Any other value returns an error.
  164. func ParseBool(val interface{}) (value bool, err error) {
  165. if val != nil {
  166. switch v := val.(type) {
  167. case bool:
  168. return v, nil
  169. case string:
  170. switch v {
  171. case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "Y", "y", "ON", "on", "On":
  172. return true, nil
  173. case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "N", "n", "OFF", "off", "Off":
  174. return false, nil
  175. }
  176. case int8, int32, int64:
  177. strV := fmt.Sprintf("%s", v)
  178. if strV == "1" {
  179. return true, nil
  180. } else if strV == "0" {
  181. return false, nil
  182. }
  183. case float64:
  184. if v == 1 {
  185. return true, nil
  186. } else if v == 0 {
  187. return false, nil
  188. }
  189. }
  190. return false, fmt.Errorf("parsing %q: invalid syntax", val)
  191. }
  192. return false, fmt.Errorf("parsing <nil>: invalid syntax")
  193. }
  194. // ToString converts values of any type to string.
  195. func ToString(x interface{}) string {
  196. switch y := x.(type) {
  197. // Handle dates with special logic
  198. // This needs to come above the fmt.Stringer
  199. // test since time.Time's have a .String()
  200. // method
  201. case time.Time:
  202. return y.Format("A Monday")
  203. // Handle type string
  204. case string:
  205. return y
  206. // Handle type with .String() method
  207. case fmt.Stringer:
  208. return y.String()
  209. // Handle type with .Error() method
  210. case error:
  211. return y.Error()
  212. }
  213. // Handle named string type
  214. if v := reflect.ValueOf(x); v.Kind() == reflect.String {
  215. return v.String()
  216. }
  217. // Fallback to fmt package for anything else like numeric types
  218. return fmt.Sprint(x)
  219. }