使用golang库props轻松使用配置源文件,zookeeper、consul

tietang · 2017-09-09 06:04:42 · 5397 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2017-09-09 06:04:42 的主题,其中的信息可能已经有所发展或是发生改变。

props是统一的配置工具库,将各种配置源抽象或转换为类似properties格式的key/value,并提供统一的API来访问这些key/value。支持 properties 文件、ini 文件、zookeeper k/v、zookeeper k/props、consul k/v、consul k/props等配置源,并且支持通过 Unmarshal从配置中抽出struct;支持上下文环境变量的eval,`${}`形式;支持多种配置源组合使用。

github地址:https://github.com/tietang/props

props

统一的配置工具库,将各种配置源抽象或转换为类似properties格式的key/value,并提供统一的API来访问这些key/value。

特性

支持的配置源:

  • properties文件
  • ini文件
  • zookeeper k/v
  • zookeeper k/props
  • consul k/v
  • consul k/props

key/value支持的数据类型:

  • key只支持string
  • value 5种数据类型的支持:
    • string
    • int
    • float64
    • bool
    • time.Duration:
      • 比如 "300ms", "-1.5h" or "2h45m".
      • 合法的时间单位: "ns", "us" (or "µs"), "ms", "s", "m", "h".

其他特性

  • Unmarshal支持
  • 上下文变量eval支持,${}形式
  • 支持多配置源组合

Install

运行deps.sh安装依赖。

或者

参考 golang dep使用dep命令来安装。

配置源和配置形式使用方法:

properties格式文件

格式:[key][=|:][value] \n 每行为key/value键值对 ,用=分割,key可以是除了=:、以及空白字符的任何字符

例子:

server.port=8080

或者

server.port: 8080

通过props.ReadPropertyFile读取文件


p, err := props.ReadPropertyFile("config.properties")
if err != nil {
    panic(err)
}
stringValue, err := p.Get("prefix.key1")
//如果不存在,则返回默认值
stringDefaultValue := p.GetDefault("prefix.key1", "default value")
boolValue, err := p.GetBool("prefix.key1")
boolDefaultValue := p.GetBoolDefault("prefix.key1", false)
intValue, err := p.GetInt("prefix.key1")
intDefaultValue := p.GetIntDefault("prefix.key1", 1)
floatValue, err := p.GetFloat64("prefix.key1")
floatDefaultValue := p.GetFloat64Default("prefix.key1", 1.2)
v, err := p.GetDuration("k9")
v := p.GetDurationDefault("k12", 1*time.Second)

通过props.NewProperties()从io.Reader中读取

 p := props.NewProperties()
 p.Load(strings.NewReader("some data"))
 p.Load(bytes.NewReader([]byte("some data")))

通过props.NewPropertiesConfigSource()

file := "/path/to/config.properties"
p := props.NewPropertiesConfigSource(file)
p = props.NewPropertiesConfigSourceByFile("name", file)
//通过map构造内存型
m := make(map[string]string)
m["key"]="value"
p = props.NewPropertiesConfigSourceByMap("name", m)

Properties ConfigSource


var cs props.ConfigSource
//
cs = props.NewPropertiesConfigSource("config.properties")
cs = props.NewPropertiesConfigSourceByFile("config", "config.properties")


stringValue, err := cs.Get("prefix.key1")
//如果不存在,则返回默认值
stringDefaultValue := cs.GetDefault("prefix.key1", "default value")
boolValue, err := cs.GetBool("prefix.key2")
boolDefaultValue := cs.GetBoolDefault("prefix.key2", false)
intValue, err := cs.GetInt("prefix.key3")
intDefaultValue := cs.GetIntDefault("prefix.key3", 1)
floatValue, err := cs.GetFloat64("prefix.key4")
floatDefaultValue := cs.GetFloat64Default("prefix.key4", 1.2)

ini格式文件。

格式:参考 wiki百科:INI_file

[section]
[key1][=|:][value1] 
[key1][=|:][value1]
...

不支持sub section

例子:

[server]
port: 8080
read.timeout=6000ms

[client]
connection.timeout=6s
query.timeout=6s

使用方法:

file := "/path/to/config.ini"
p := props.NewIniFileConfigSource(file)
p = props.NewIniFileConfigSourceByFile("name", file)

zookeeper

支持key/value和key/properties配置形式,key/properties配置和ini类似,将key作为section name。 key/value形式,将path去除root path部分并替换/.作为key。 key/properties形式,在root path下读取所有子节点,将子节点名称作为section name,value为子properties格式内存,通过子节点名称和子properties中的key组合成新的key作为key。

by zookeeper key/value

基本例子
root := "/config/kv/app1/dev"
var conn *zk.Conn
p := props.NewZookeeperConfigSource("zookeeper-kv", root, conn)
CompositeConfigSource多context例子
var cs props.ConfigSource
urls := []string{"172.16.1.248:2181"}
contexts := []string{"/configs/apps","/configs/users"}
cs = props.NewZookeeperCompositeConfigSource(contexts, urls, time.Second*3)

用properties来配置: key/properties

value值为properties格式内容, 整体设计类似ini格式

root := "/config/kv/app1/dev"
var conn *zk.Conn
p := props.NewZookeeperIniConfigSource("zookeeper-kv", root, conn)

consul 多层key/value形式

by consul key/value

例如:

config101/test/demo1/server/port=8080

获取的属性和值是:

server.port=8080

address := "127.0.0.1:8500"
root := "config101/test/demo1"
c := NewConsulKeyValueConfigSource("consul", address, root)
stringValue, err := cs.Get("prefix.key1")
stringDefaultValue := cs.GetDefault("prefix.key1", "default value")

用properties来配置: key/properties

value值为properties格式内容, 整体设计类似ini格式

root := "config/app1/dev"
address := "127.0.0.1:8500"
p := props.NewConsulIniConfigSourceByName("consul-ini", address, root)

支持Unmarshal

支持的数据类型:

  • int,int8,int16,int32,int64
  • uint,uint8,uint16,uint32,uint64
  • string
  • bool
  • float32,float64
  • time.Duration
  • 嵌套struct
  • map:key只支持string,value支持以上除struct的基本类型

在struct中规定命名为_prefix、类型为string、并且指定了prefixtag, 使用feild _prefixprefixtag作为前缀,将struct feild名称转换后组合成完整的key,并从ConfigSource中获取数据并注入struct实例,feild类型只支持ConfigSource所支持的数据类型(string、int、float、bool、time.Duration)。



type Port struct {
    Port    int  `val:"8080"`
    Enabled bool `val:"true"`
}
type ServerProperties struct {
    _prefix string        `prefix:"http.server"`
    Port    Port
    Timeout int           `val:"1"`
    Enabled bool
    Foo     int           `val:"1"`
    Time    time.Duration `val:"1s"`
    Float   float32       `val:"0.000001"`
    Params  map[string]string
    Times      map[string]time.Duration
}

func main() {

    p := props.NewMapProperties()
    p.Set("http.server.port.port", "8080")
    p.Set("http.server.params.k1", "v1")
    p.Set("http.server.params.k2", "v2")
    p.Set("http.server.Times.m1", "1s")
    p.Set("http.server.Times.m2", "1h")
    p.Set("http.server.Times.m3", "1us")
    p.Set("http.server.port.enabled", "false")
    p.Set("http.server.timeout", "1234")
    p.Set("http.server.enabled", "true")
    p.Set("http.server.time", "10s")
    p.Set("http.server.float", "23.45")
    p.Set("http.server.foo", "23")
    s := &ServerProperties{
        Foo:   1234,
        Float: 1234.5,
    }
    p.Unmarshal(s)
    fmt.Println(s)

}

上下文变量表达式(或者占位符)的支持

支持在props上下文中替换占位符:${}

p := NewEmptyMapConfigSource("map2")
p.Set("orign.key1", "v1")
p.Set("orign.key2", "v2")
p.Set("orign.key3", "2")
p.Set("ph.key1", "${orign.key1}")
p.Set("ph.key2", "${orign.key1}:${orign.key2}")
p.Set("ph.key3", "${orign.key3}")
conf := NewDefaultCompositeConfigSource(p)
phv1, err := conf.GetInt("ph.key1")//v1
phv2, err := conf.Get("ph.key2")//v1:v1
phv3, err := conf.GetInt("ph.key3")//2

多种配置源组合使用

优先级以追加相反的顺序,最后添加优先级最高。


kv1 := []string{"go.app.key1", "value1", "value1-2"}
kv2 := []string{"go.app.key2", "value2", "value2-2"}

p1 := NewEmptyMapConfigSource("map1")
p1.Set(kv1[0], kv1[1])
p1.Set(kv2[0], kv2[1])
p2 := NewEmptyMapConfigSource("map2")
p2.Set(kv1[0], kv1[2])
p2.Set(kv2[0], kv2[2])
conf.Add(p1)
conf.Add(p2)

//value1==value1-2
value1, err := conf.Get(kv1[0])
fmt.Println(value1)
//value2=value2-2
value2, err := conf.Get(kv2[0])
fmt.Println(value2)

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

5397 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传