properties.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. package conf
  2. import (
  3. "fmt"
  4. "os"
  5. "strconv"
  6. "strings"
  7. "sync"
  8. "git.i2edu.net/i2/go-zero/core/iox"
  9. )
  10. // PropertyError represents a configuration error message.
  11. type PropertyError struct {
  12. error
  13. message string
  14. }
  15. // Properties interface provides the means to access configuration.
  16. type Properties interface {
  17. GetString(key string) string
  18. SetString(key, value string)
  19. GetInt(key string) int
  20. SetInt(key string, value int)
  21. ToString() string
  22. }
  23. // Properties config is a key/value pair based configuration structure.
  24. type mapBasedProperties struct {
  25. properties map[string]string
  26. lock sync.RWMutex
  27. }
  28. // LoadProperties loads the properties into a properties configuration instance.
  29. // Returns an error that indicates if there was a problem loading the configuration.
  30. func LoadProperties(filename string, opts ...Option) (Properties, error) {
  31. lines, err := iox.ReadTextLines(filename, iox.WithoutBlank(), iox.OmitWithPrefix("#"))
  32. if err != nil {
  33. return nil, err
  34. }
  35. var opt options
  36. for _, o := range opts {
  37. o(&opt)
  38. }
  39. raw := make(map[string]string)
  40. for i := range lines {
  41. pair := strings.Split(lines[i], "=")
  42. if len(pair) != 2 {
  43. // invalid property format
  44. return nil, &PropertyError{
  45. message: fmt.Sprintf("invalid property format: %s", pair),
  46. }
  47. }
  48. key := strings.TrimSpace(pair[0])
  49. value := strings.TrimSpace(pair[1])
  50. if opt.env {
  51. raw[key] = os.ExpandEnv(value)
  52. } else {
  53. raw[key] = value
  54. }
  55. }
  56. return &mapBasedProperties{
  57. properties: raw,
  58. }, nil
  59. }
  60. func (config *mapBasedProperties) GetString(key string) string {
  61. config.lock.RLock()
  62. ret := config.properties[key]
  63. config.lock.RUnlock()
  64. return ret
  65. }
  66. func (config *mapBasedProperties) SetString(key, value string) {
  67. config.lock.Lock()
  68. config.properties[key] = value
  69. config.lock.Unlock()
  70. }
  71. func (config *mapBasedProperties) GetInt(key string) int {
  72. config.lock.RLock()
  73. // default 0
  74. value, _ := strconv.Atoi(config.properties[key])
  75. config.lock.RUnlock()
  76. return value
  77. }
  78. func (config *mapBasedProperties) SetInt(key string, value int) {
  79. config.lock.Lock()
  80. config.properties[key] = strconv.Itoa(value)
  81. config.lock.Unlock()
  82. }
  83. // ToString dumps the configuration internal map into a string.
  84. func (config *mapBasedProperties) ToString() string {
  85. config.lock.RLock()
  86. ret := fmt.Sprintf("%s", config.properties)
  87. config.lock.RUnlock()
  88. return ret
  89. }
  90. // Error returns the error message.
  91. func (configError *PropertyError) Error() string {
  92. return configError.message
  93. }
  94. // NewProperties builds a new properties configuration structure.
  95. func NewProperties() Properties {
  96. return &mapBasedProperties{
  97. properties: make(map[string]string),
  98. }
  99. }