Как обрабатывать конфигурацию в Go

Я новичок в программировании на Go, и мне интересно: каков предпочтительный способ обработки параметров конфигурации для программы на Go (для чего можно использовать файлы свойств или файлы ini, в других контекстах)?

13 ответов

Решение

Формат JSON работал для меня довольно хорошо. Стандартная библиотека предлагает методы для записи структуры данных с отступом, поэтому она вполне читаема.

Смотрите также эту нить голанг-орехов.

Преимущества JSON заключаются в том, что его довольно просто анализировать и читать / редактировать человеком, предлагая семантику для списков и отображений (что может оказаться весьма удобным), что не имеет места для многих конфигурационных парсеров ini-типа.

Пример использования:

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]

Другой вариант - использовать TOML, который является INI-подобным форматом, созданным Томом Престоном-Вернером. Я построил парсер Go для него, который тщательно протестирован. Вы можете использовать его, как и другие варианты, предложенные здесь. Например, если у вас есть эти данные TOML в something.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
}

Viper - это система управления конфигурацией golang, которая работает с JSON, YAML и TOML. Это выглядит довольно интересно.

Я обычно использую JSON для более сложных структур данных. Недостатком является то, что вы легко получаете кучу кода, чтобы сообщить пользователю, где была ошибка, различные крайние случаи, а что нет.

Для базовой конфигурации (ключи API, номера портов,...) мне очень повезло с пакетом gcfg. Он основан на формате git config.

Из документации:

Пример конфигурации:

; 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")

Он также поддерживает значения срезов, так что вы можете разрешить указывать ключ несколько раз и другие полезные функции, подобные этому.

Просто используйте стандартные флаги go с iniflags.

Стандартные флаги go имеют следующие преимущества:

  • Идиоматические.
  • Легко использовать. Флаги могут быть легко добавлены и разбросаны по произвольным пакетам, которые использует ваш проект.
  • Флаги имеют встроенную поддержку значений и описания по умолчанию.
  • Флаги предоставляют стандартный вывод справки со значениями по умолчанию и описанием.

Единственный недостаток стандартных флагов go - это проблемы управления, когда количество флагов, используемых в вашем приложении, становится слишком большим.

Iniflags элегантно решает эту проблему: просто измените две строки в вашем основном пакете, и он волшебным образом получит поддержку чтения значений флагов из INI-файла. Флаги из INI-файлов могут быть переопределены путем передачи новых значений в командной строке.

См. Также https://groups.google.com/forum/ подробности.

Я начал использовать 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
}

Взгляни на гонфиг

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

https://github.com/spf13/viper и https://github.com/zpatrick/go-config - довольно хорошие библиотеки для файлов конфигурации.

Используйте toml, как эта статья. Чтение конфигурационных файлов.

Я написал простую конфигурационную библиотеку ini на Голанге.

https://github.com/c4pt0r/cfg

безопасен при использовании рутин, прост в использовании

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=======================

В последнее время мне нужен анализатор INI с поддержкой разделов, и я пишу простой пакет:

github.com/c4pt0r/cfg

Вы можете анализировать INI, например, используя пакет "flag":

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

Вас также может заинтересовать go-libucl, набор привязок Go для UCL, универсальный язык конфигурации. UCL немного похож на JSON, но с лучшей поддержкой для людей: он поддерживает комментарии и удобочитаемые конструкции, такие как множители SI (10k, 40M и т. Д.), И имеет немного меньший шаблон (например, кавычки вокруг ключей). На самом деле это довольно близко к формату файла конфигурации nginx, если вы уже знакомы с этим.

Я согласен с nemo и написал небольшой инструмент, чтобы все было по-настоящему легко.

http://bitbucket.org/gotamer/cfg - это пакет конфигурации json

  • Вы определяете свои элементы конфигурации в своем приложении как структура.
  • Шаблон файла конфигурации json из вашей структуры сохраняется при первом запуске
  • Вы можете сохранить изменения времени выполнения в конфигурации

Смотрите doc.go для примера

Я попробовал JSON. Это сработало. Но я ненавижу создавать структуру точных полей и типов, которые я могу задавать. Для меня это было болью. Я заметил, что это был метод, используемый всеми опциями конфигурации, которые я мог найти. Возможно, мой опыт работы с динамическими языками делает меня слепым к преимуществам такой многословности. Я сделал новый простой формат файла конфигурации и более динамическую библиотеку для его чтения.

https://github.com/chrisftw/ezconf

Я довольно новичок в мире Го, так что это может быть не путь Го. Но это работает, это довольно быстро и очень просто в использовании.

Pros

  • Супер просто
  • Меньше кода

Cons

  • Нет массивов или типов карт
  • Очень плоский формат файла
  • Нестандартные файлы conf
  • Есть небольшая встроенная конвенция, которую я сейчас, если вообще не одобряю, в сообществе Go. (Ищет файл конфигурации в каталоге конфигурации)
Другие вопросы по тегам