零零乙
2013-05-09 15:41
采纳率: 50%
浏览 349

如何处理 Go [关闭]中的配置

I'm new at Go programming, and I'm wondering: what is the preferred way to handle configuration parameters for a Go program (the kind of stuff one might use properties files or ini files for, in other contexts)?

转载于:https://stackoverflow.com/questions/16465705/how-to-handle-configuration-in-go

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

12条回答 默认 最新

  • 游.程 2013-05-09 16:05
    已采纳

    The JSON format worked for me quite well. The standard library offers methods to write the data structure indented, so it is quite readable.

    See also this golang-nuts thread.

    The benefits of JSON are that it is fairly simple to parse and human readable/editable while offering semantics for lists and mappings (which can become quite handy), which is not the case with many ini-type config parsers.

    Example usage:

    conf.json:

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

    Program to read the configuration

    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]
    
    已采纳该答案
    打赏 评论
  • from.. 2013-05-09 16:38

    I usually use JSON for more complicated data structures. The downside is that you easily end up with a bunch of code to tell the user where the error was, various edge cases and what not.

    For base configuration (api keys, port numbers, ...) I've had very good luck with the gcfg package. It is based on the git config format.

    From the documentation:

    Sample config:

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

    Go struct:

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

    And the code needed to read it:

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

    It also supports slice values, so you can allow specifying a key multiple times and other nice features like that.

    打赏 评论
  • 笑故挽风 2013-05-10 09:02

    I have started using Gcfg which uses Ini-like files. It's simple - if you want something simple, this is a good choice.

    Here's the loading code I am using currently, which has default settings and allows command line flags (not shown) that override some of my config:

    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
    }
    
    打赏 评论
  • 北城已荒凉 2013-05-10 22:01

    Another option is to use TOML, which is an INI-like format created by Tom Preston-Werner. I built a Go parser for it that is extensively tested. You can use it like other options proposed here. For example, if you have this TOML data in something.toml

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

    Then you can load it into your Go program with something like

    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
    }
    
    打赏 评论
  • 叼花硬汉 2013-12-27 02:07

    I agree with nemo and I wrote a little tool to make it all real easy.

    bitbucket.org/gotamer/cfg is a json configuration package

    • You define your config items in your application as a struct.
    • A json config file template from your struct is saved on the first run
    • You can save runtime modifications to the config

    See doc.go for an example

    打赏 评论
  • elliott.david 2014-05-07 07:48

    I wrote a simple ini config library in golang.

    https://github.com/c4pt0r/cfg

    goroutine-safe, easy to use

    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)
        }
    }
    

    ===================Update=======================

    Recently I need an INI parser with section support, and I write a simple package:

    github.com/c4pt0r/cfg
    

    u can parse INI like using "flag" package:

    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)
    }
    
    打赏 评论
  • elliott.david 2014-08-15 09:32

    Just use standard go flags with iniflags.

    Standard go flags have the following benefits:

    • Idiomatic.
    • Easy to use. Flags can be easily added and scattered across arbitrary packages your project uses.
    • Flags have out-of-the-box support for default values and description.
    • Flags provide standard 'help' output with default values and description.

    The only drawback standard go flags have - is management problems when the number of flags used in your app becomes too large.

    Iniflags elegantly solves this problem: just modify two lines in your main package and it magically gains support for reading flag values from ini file. Flags from ini files can be overriden by passing new values in command-line.

    See also https://groups.google.com/forum/#!topic/golang-nuts/TByzyPgoAQE for details.

    打赏 评论
  • MAO-EYE 2015-05-05 03:03

    You might also be interested in go-libucl, a set of Go bindings for UCL, the Universal Configuration Language. UCL is a bit like JSON, but with better support for humans: it supports comments and human-readable constructs like SI multipliers (10k, 40M, etc.) and has a little bit less boilerplate (e.g., quotes around keys). It's actually pretty close to the nginx configuration file format, if you're already familiar with that.

    打赏 评论
  • csdnceshi62 2015-08-27 16:12

    I tried JSON. It worked. But I hate having to create the struct of the exact fields and types I might be setting. To me that was a pain. I noticed it was the method used by all the configuration options I could find. Maybe my background in dynamic languages makes me blind to the benefits of such verboseness. I made a new simple config file format, and a more dynamic-ish lib for reading it out.

    https://github.com/chrisftw/ezconf

    I am pretty new to the Go world, so it might not be the Go way. But it works, it is pretty quick, and super simple to use.

    Pros

    • Super simple
    • Less code

    Cons

    • No Arrays or Map types
    • Very flat file format
    • Non-standard conf files
    • Does have a little convention built-in, which I now if frowned upon in general in Go community. (Looks for config file in the config directory)
    打赏 评论
  • 程序go 2015-10-29 10:00

    Use toml like this article Reading config files the Go way

    打赏 评论
  • 三生石@ 2015-11-16 05:35

    have a look at 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)
    
    打赏 评论
  • 喵-见缝插针 2015-11-16 21:30

    https://github.com/spf13/viper and https://github.com/zpatrick/go-config are a pretty good libraries for configuration files.

    打赏 评论

相关推荐 更多相似问题