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