在Go中如何处理配置

我是Go编程的新手,我想知道:处理Go程序的配置参数的首选方式是什么(在其他情况下,可能会使用属性文件或ini文件的那种东西)?

225950 次浏览
JSON格式对我来说很好。的 标准库提供了缩进写入数据结构的方法,因此它是相当 可读性。< / p >

另见这条高朗坚果线

JSON的好处是它相当简单,易于解析和人类可读/编辑 同时为列表和映射提供语义(这可能会变得非常方便)

使用示例:

conf.json:

{
"Users": ["UserA","UserB"],
"Groups": ["GroupA"]
}

程序读取配置

import (
"encoding/json"
"os"
"fmt"
)


type Configuration struct {
Users    []string
Groups   []string
}


file, _ := os.Open("conf.json")
defer file.Close()
decoder := json.NewDecoder(file)
configuration := Configuration{}
err := decoder.Decode(&configuration)
if err != nil {
fmt.Println("error:", err)
}
fmt.Println(configuration.Users) // output: [UserA, UserB]

对于更复杂的数据结构,我通常使用JSON。缺点是,您很容易以一堆代码来告诉用户错误在哪里、各种边缘情况和其他情况。

对于基本配置(api密钥,端口号,…)我在gcfg包上有非常好的运气。它基于git配置格式。

从文档中可以看到:

示例配置:

; Comment line
[section]
name = value # Another comment
flag # implicit value for bool is true

结构:

type Config struct {
Section struct {
Name string
Flag bool
}
}

读取它所需的代码:

var cfg Config
err := gcfg.ReadFileInto(&cfg, "myconfig.gcfg")

它还支持切片值,因此您可以允许多次指定一个键和其他类似的好特性。

我已经开始使用Gcfg,它使用类似ini的文件。它很简单——如果你想要一些简单的东西,这是一个很好的选择。

下面是我目前使用的加载代码,它有默认设置,并允许命令行标志(未显示)覆盖我的一些配置:

package util


import (
"code.google.com/p/gcfg"
)


type Config struct {
Port int
Verbose bool
AccessLog string
ErrorLog string
DbDriver string
DbConnection string
DbTblPrefix string
}


type configFile struct {
Server Config
}


const defaultConfig = `
[server]
port = 8000
verbose = false
accessLog = -
errorLog  = -
dbDriver     = mysql
dbConnection = testuser:TestPasswd9@/test
dbTblPrefix  =
`


func LoadConfiguration(cfgFile string, port int, verbose bool) Config {
var err error
var cfg configFile


if cfgFile != "" {
err = gcfg.ReadFileInto(&cfg, cfgFile)
} else {
err = gcfg.ReadStringInto(&cfg, defaultConfig)
}


PanicOnError(err)


if port != 0 {
cfg.Server.Port = port
}
if verbose {
cfg.Server.Verbose = true
}


return cfg.Server
}

另一种选择是使用TOML,这是Tom Preston-Werner创建的一种类似ini的格式。我为它构建了一个Go解析器,这是广泛的测试。您可以像这里建议的其他选项一样使用它。例如,如果你在something.toml中有这个TOML数据

Age = 198
Cats = [ "Cauchy", "Plato" ]
Pi = 3.14
Perfection = [ 6, 28, 496, 8128 ]
DOB = 1987-07-05T05:45:00Z

然后你可以把它加载到你的Go程序中

type Config struct {
Age int
Cats []string
Pi float64
Perfection []int
DOB time.Time
}


var conf Config
if _, err := toml.DecodeFile("something.toml", &conf); err != nil {
// handle error
}

我同意尼莫,我写了一个小工具,使这一切都很容易。

bitbucket.org/gotamer/cfg是一个json配置包

  • 将应用程序中的配置项定义为结构。
  • 在第一次运行时保存struct中的json配置文件模板
  • 您可以保存对配置的运行时修改

看医生。举个例子

我用golang写了一个简单的ini配置库。

https://github.com/c4pt0r/cfg

gorroutine安全,易于使用

package cfg
import (
"testing"
)


func TestCfg(t *testing.T) {
c := NewCfg("test.ini")
if err := c.Load() ; err != nil {
t.Error(err)
}
c.WriteInt("hello", 42)
c.WriteString("hello1", "World")


v, err := c.ReadInt("hello", 0)
if err != nil || v != 42 {
t.Error(err)
}


v1, err := c.ReadString("hello1", "")
if err != nil || v1 != "World" {
t.Error(err)
}


if err := c.Save(); err != nil {
t.Error(err)
}
}

=================== 更新 =======================

最近,我需要一个INI解析器与节支持,我写了一个简单的包:

github.com/c4pt0r/cfg

你可以像使用"flag"包一样解析INI:

package main


import (
"log"
"github.com/c4pt0r/ini"
)


var conf = ini.NewConf("test.ini")


var (
v1 = conf.String("section1", "field1", "v1")
v2 = conf.Int("section1", "field2", 0)
)


func main() {
conf.Parse()


log.Println(*v1, *v2)
}

只要使用标准的去的旗帜iniflags

去的旗帜

import "flag"
var nFlag = flag.Int("n", 1234, "help message for flag n")

iniflags

package main


import (
"flag"
...
"github.com/vharitonsky/iniflags"
...
)


var (
flag1 = flag.String("flag1", "default1", "Description1")
...
flagN = flag.Int("flagN", 123, "DescriptionN")
)


func main() {
iniflags.Parse()  // use instead of flag.Parse()
}

标准go标志有以下好处:

  • 惯用。
  • 使用方便。标志可以很容易地添加并分散在项目使用的任意包中。
  • 标志对默认值和描述有开箱即用的支持。
  • 标志提供带有默认值和描述的标准“帮助”输出。

标准go标志的唯一缺点是,当你的应用程序中使用的标志数量过大时,会出现管理问题。

Iniflags巧妙地解决了这个问题:只需修改主包中的两行,它就神奇地获得了从ini文件读取标志值的支持。ini文件中的标志可以通过在命令行中传递新值来覆盖。

详情请参见https://groups.google.com/forum/ !主题/ golang-nuts / TByzyPgoAQE

毒蛇是一个与JSON、YAML和TOML一起工作的golang配置管理系统。看起来很有趣。

你可能也会对go-libucl感兴趣,它是一组通用配置语言UCL的Go绑定。UCL有点像JSON,但对人类有更好的支持:它支持注释和人类可读的结构,如SI乘子(10k, 40M等),并且有更少的模板(例如,键周围的引号)。它实际上非常接近nginx配置文件格式,如果你已经熟悉它的话。

我尝试了JSON。它工作。但我讨厌必须创建我可能要设置的确切字段和类型的结构体。对我来说,这是一种痛苦。我注意到,我能找到的所有配置选项都使用这种方法。也许我在动态语言方面的背景让我看不到这种冗长的好处。我制作了一个新的简单配置文件格式,以及一个更动态的库来读取它。

https://github.com/chrisftw/ezconf

我对围棋世界很陌生,所以这可能不是围棋的方式。但是它很有效,非常快,而且使用起来超级简单。

优点

  • 超级简单的
  • 更少的代码

缺点

  • 没有数组或Map类型
  • 非常平面的文件格式
  • 非标准的conf文件
  • 它有一个内置的小约定,我现在在围棋社区普遍不赞成这个约定。(在config目录中查找配置文件)

看看gonfig

// load
config, _ := gonfig.FromJson(myJsonFile)
// read with defaults
host, _ := config.GetString("service/host", "localhost")
port, _ := config.GetInt("service/port", 80)
test, _ := config.GetBool("service/testing", false)
rate, _ := config.GetFloat("service/rate", 0.0)
// parse section into target structure
config.GetAs("service/template", &template)