package properties import ( "bufio" "bytes" "io" "strings" "sync" "git.shuncheng.lu/bigthing/gocommon/pkg/internal/util" ) type Properties interface { // changeMap 切片两个值,第一个是老得值,第二个是新的值,并发安全 DiffProperties(pro Properties) (deleteMap, addMap map[string]string, changeMap map[string][]string) SetString(key string, value string) GetString(key string, defaultValue ...string) (value string) GetBool(key string, defaultValue ...bool) (value bool) GetInt64(key string, defaultValue ...int64) (value int64) GetUint64(key string, defaultValue ...uint64) (value uint64) GetFloat64(key string, defaultValue ...float64) (value float64) GetAll() map[string]string } type properties struct { config map[string]string sync.RWMutex } func NewProperties() Properties { return &properties{ config: map[string]string{}, } } func ReadFromBytes(content []byte) (Properties, error) { config, err := readStr(content) if err != nil { return nil, err } return &properties{ config: config, }, nil } func ReadFromString(content string) (Properties, error) { config, err := readStr([]byte(content)) if err != nil { return nil, err } return &properties{ config: config, }, nil } func ReadFromReader(reader io.Reader) (Properties, error) { config, err := readReader(reader) if err != nil { return nil, err } return &properties{ config: config, }, nil } func (p *properties) GetString(key string, defaultValue ...string) string { p.RLock() defer p.RUnlock() value, isExist := p.config[key] if !isExist || value == "" { if defaultValue == nil || len(defaultValue) == 0 { return "" } return defaultValue[0] } return value } func (p *properties) SetString(key string, value string) { p.Lock() defer p.Unlock() p.config[key] = value } func (p *properties) GetInt64(key string, defaultValue ...int64) (value int64) { p.RLock() defer p.RUnlock() return util.String2Int64(p.config[key], defaultValue...) } func (p *properties) GetUint64(key string, defaultValue ...uint64) (value uint64) { p.RLock() defer p.RUnlock() return util.String2Uint64(p.config[key], defaultValue...) } func (p *properties) GetFloat64(key string, defaultValue ...float64) (value float64) { p.RLock() defer p.RUnlock() return util.String2Float64(p.config[key], defaultValue...) } func (p *properties) GetBool(key string, defaultValue ...bool) (value bool) { p.RLock() defer p.RUnlock() return util.String2Bool(p.config[key], defaultValue...) } func (p *properties) GetAll() map[string]string { p.RLock() defer p.RUnlock() result := make(map[string]string, len(p.config)) for key, value := range p.config { result[key] = value } return result } func readStr(str []byte) (map[string]string, error) { if str == nil || len(str) == 0 { return map[string]string{}, nil } buffer := bytes.Buffer{} _, err := buffer.Write(str) if err != nil { return nil, err } return readReader(&buffer) } func readReader(reader io.Reader) (map[string]string, error) { if reader == nil { return map[string]string{}, nil } r := bufio.NewReader(reader) config := make(map[string]string, 0) for { b, _, err := r.ReadLine() if err != nil { if err == io.EOF { break } return nil, err } s := strings.TrimSpace(string(b)) if s == "" { continue } if s[0] == '#' { // 过滤注释 continue } // 获取key=value index := strings.Index(s, "=") if index < 0 { continue } key := strings.TrimSpace(s[:index]) if len(key) == 0 { continue } value := strings.TrimSpace(s[index+1:]) if len(value) == 0 { continue } config[key] = value } return config, nil } func (p *properties) DiffProperties(pro Properties) (deleteMap, addMap map[string]string, changeMap map[string][]string) { oldConfig := p.GetAll() newConfig := pro.GetAll() return util.DiffMap(oldConfig, newConfig) }