Eu sou novo na programação Go e me pergunto: qual é a maneira preferida de lidar com parâmetros de configuração para um programa Go (o tipo de coisa que se pode usar arquivos de propriedades ou arquivos ini para, em outros contextos)?
Eu sou novo na programação Go e me pergunto: qual é a maneira preferida de lidar com parâmetros de configuração para um programa Go (o tipo de coisa que se pode usar arquivos de propriedades ou arquivos ini para, em outros contextos)?
Respostas:
O formato JSON funcionou muito bem para mim. A biblioteca padrão oferece métodos para escrever a estrutura de dados recuada, portanto é bastante legível.
Veja também este fio de nozes golang .
Os benefícios do JSON são que é bastante simples analisar e legível / editável por humanos, oferecendo semântica para listas e mapeamentos (que podem se tornar bastante úteis), o que não é o caso de muitos analisadores de configuração do tipo ini.
Exemplo de uso:
conf.json :
{
"Users": ["UserA","UserB"],
"Groups": ["GroupA"]
}
Programa para ler a configuração
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]
defer file.Close()
depois de verificar o erro em aberto
Outra opção é usar o TOML , que é um formato semelhante ao INI criado por Tom Preston-Werner. Eu construído um analisador Vá para ele que é extensivamente testado . Você pode usá-lo como outras opções propostas aqui. Por exemplo, se você tiver esses dados TOML emsomething.toml
Age = 198
Cats = [ "Cauchy", "Plato" ]
Pi = 3.14
Perfection = [ 6, 28, 496, 8128 ]
DOB = 1987-07-05T05:45:00Z
Em seguida, você pode carregá-lo no seu programa Go com algo como
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
}
O Viper é um sistema de gerenciamento de configuração golang que funciona com JSON, YAML e TOML. Parece bem interessante.
Eu costumo usar JSON para estruturas de dados mais complicadas. A desvantagem é que você acaba facilmente com um monte de código para informar ao usuário onde estava o erro, vários casos extremos e quais não.
Para a configuração básica (chaves api, números de portas, ...), tive muita sorte com o pacote gcfg . É baseado no formato de configuração do git.
A partir da documentação:
Exemplo de configuração:
; Comment line
[section]
name = value # Another comment
flag # implicit value for bool is true
Vá struct:
type Config struct {
Section struct {
Name string
Flag bool
}
}
E o código necessário para lê-lo:
var cfg Config
err := gcfg.ReadFileInto(&cfg, "myconfig.gcfg")
Ele também suporta valores de fatia, para que você possa especificar uma chave várias vezes e outros recursos interessantes como esse.
Basta usar sinalizadores padrão com iniflags .
Os sinalizadores padrão go têm os seguintes benefícios:
O único problema de sinalização padrão dos sinalizadores - são os problemas de gerenciamento quando o número de sinalizadores usados no seu aplicativo se torna muito grande.
O Iniflags resolve elegantemente esse problema: apenas modifique duas linhas no seu pacote principal e magicamente ganha suporte para a leitura de valores de flag do arquivo ini. Os sinalizadores dos arquivos ini podem ser substituídos passando novos valores na linha de comando.
Consulte também https://groups.google.com/forum/#!topic/golang-nuts/TByzyPgoAQE para obter detalhes.
go test
não me deixa passar sinalizadores) enquanto um arquivo de configuração não.
*FlagName = value
Comecei a usar o Gcfg, que usa arquivos semelhantes ao Ini. É simples - se você quiser algo simples, é uma boa escolha.
Aqui está o código de carregamento que estou usando atualmente, que possui configurações padrão e permite sinalizadores de linha de comando (não mostrados) que substituem algumas das minhas configurações:
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
}
dê uma olhada no 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)
https://github.com/spf13/viper e https://github.com/zpatrick/go-config são boas bibliotecas para arquivos de configuração.
Use toml como este artigo Lendo arquivos de configuração do jeito que está
Eu escrevi uma biblioteca simples de configuração ini em Golang.
seguro para goroutine, fácil de usar
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)
}
}
=================== Atualizar =======================
Recentemente, preciso de um analisador INI com suporte à seção e escrevo um pacote simples:
github.com/c4pt0r/cfg
você pode analisar INI como usar o pacote "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)
}
Você também pode estar interessado em go-libucl , um conjunto de ligações Go para UCL, a Linguagem de Configuração Universal. A UCL é um pouco como JSON, mas com melhor suporte para humanos: suporta comentários e construções legíveis por humanos, como multiplicadores de SI (10k, 40M, etc.) e possui um pouco menos de clichê (por exemplo, aspas em torno das teclas). Na verdade, é bem parecido com o formato do arquivo de configuração do nginx, se você já está familiarizado com isso.
Eu concordo com o nemo e escrevi uma pequena ferramenta para tornar tudo muito fácil.
bitbucket.org/gotamer/cfg é um pacote de configuração do json
Veja doc.go para um exemplo
Eu tentei JSON. Funcionou. Mas eu odeio ter que criar a estrutura dos campos e tipos exatos que posso estar definindo. Para mim isso foi uma dor. Percebi que era o método usado por todas as opções de configuração que pude encontrar. Talvez minha formação em linguagens dinâmicas me torne cego para os benefícios de tal verbosidade. Criei um novo formato de arquivo de configuração simples e uma biblioteca mais dinâmica para lê-lo.
https://github.com/chrisftw/ezconf
Sou muito novo no mundo Go, por isso pode não ser o caminho. Mas funciona, é bem rápido e super simples de usar.