Sono nuovo nella programmazione Go e mi chiedo: qual è il modo preferito di gestire i parametri di configurazione per un programma Go (il tipo di cose per cui si potrebbero usare i file delle proprietà o i file ini , in altri contesti)?
Sono nuovo nella programmazione Go e mi chiedo: qual è il modo preferito di gestire i parametri di configurazione per un programma Go (il tipo di cose per cui si potrebbero usare i file delle proprietà o i file ini , in altri contesti)?
Risposte:
Il formato JSON ha funzionato abbastanza bene per me. La libreria standard offre metodi per scrivere la struttura dei dati rientrata, quindi è abbastanza leggibile.
Vedi anche questa discussione sulle noci di Golang .
I vantaggi di JSON sono che è abbastanza semplice da analizzare e leggibile / modificabile dall'uomo mentre offre semantica per elenchi e mappature (che possono diventare abbastanza utili), il che non è il caso di molti parser di configurazione di tipo ini.
Esempio di utilizzo:
conf.json :
{
"Users": ["UserA","UserB"],
"Groups": ["GroupA"]
}
Programma per leggere la configurazione
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()
dopo aver verificato open err
Un'altra opzione è usare TOML , che è un formato simile a INI creato da Tom Preston-Werner. Ho creato un parser Go per questo che è ampiamente testato . Puoi usarlo come altre opzioni proposte qui. Ad esempio, se si dispone di questi dati TOML insomething.toml
Age = 198
Cats = [ "Cauchy", "Plato" ]
Pi = 3.14
Perfection = [ 6, 28, 496, 8128 ]
DOB = 1987-07-05T05:45:00Z
Quindi puoi caricarlo nel tuo programma Go con qualcosa di simile
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 è un sistema di gestione della configurazione Golang che funziona con JSON, YAML e TOML. Sembra piuttosto interessante.
Di solito uso JSON per strutture di dati più complicate. Il rovescio della medaglia è che si finisce facilmente con un mucchio di codice per dire all'utente dove si trovava l'errore, vari casi limite e cosa no.
Per la configurazione di base (chiavi API, numeri di porta, ...) ho avuto molta fortuna con il pacchetto gcfg . Si basa sul formato di configurazione git.
Dalla documentazione:
Configurazione di esempio:
; Comment line
[section]
name = value # Another comment
flag # implicit value for bool is true
Vai strutt:
type Config struct {
Section struct {
Name string
Flag bool
}
}
E il codice necessario per leggerlo:
var cfg Config
err := gcfg.ReadFileInto(&cfg, "myconfig.gcfg")
Supporta anche i valori di sezione, quindi puoi consentire di specificare una chiave più volte e altre belle funzioni come questa.
Usa solo go-flag standard con iniflags .
I go-flag standard offrono i seguenti vantaggi:
L'unico svantaggio di go go standard presenta: sono i problemi di gestione quando il numero di flag utilizzati nella tua app diventa troppo grande.
Iniflags risolve elegantemente questo problema: basta modificare due righe nel pacchetto principale e ottiene magicamente supporto per la lettura dei valori dei flag dal file ini. I flag dei file ini possono essere sostituiti passando nuovi valori nella riga di comando.
Vedi anche https://groups.google.com/forum/#!topic/golang-nuts/TByzyPgoAQE per i dettagli.
go test
non mi lascia passare i flag) mentre un file di configurazione non lo farebbe.
*FlagName = value
Ho iniziato a usare Gcfg che utilizza file simili a Ini. È semplice: se vuoi qualcosa di semplice, questa è una buona scelta.
Ecco il codice di caricamento che sto utilizzando attualmente, che ha le impostazioni predefinite e consente i flag della riga di comando (non mostrati) che sostituiscono alcune delle mie configurazioni:
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
}
dai un'occhiata a 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 sono librerie abbastanza buone per i file di configurazione.
Usa toml come questo articolo Leggendo i file di configurazione nel modo Vai
Ho scritto una semplice libreria di configurazione in Golang.
goroutine-sicuro, facile da usare
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)
}
}
=================== Aggiornamento =======================
Di recente ho bisogno di un parser INI con supporto di sezione e scrivo un pacchetto semplice:
github.com/c4pt0r/cfg
puoi analizzare INI come usare il pacchetto "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)
}
Potresti anche essere interessato a go-libucl , una serie di collegamenti Go per UCL, Universal Configuration Language. UCL è un po 'come JSON, ma con un migliore supporto per l'uomo: supporta commenti e costrutti leggibili dall'uomo come moltiplicatori SI (10k, 40M, ecc.) E ha un po' meno plateplate (ad esempio, virgolette attorno alle chiavi). In realtà è abbastanza vicino al formato del file di configurazione nginx, se lo conosci già.
Sono d'accordo con nemo e ho scritto un piccolo strumento per rendere tutto molto semplice.
bitbucket.org/gotamer/cfg è un pacchetto di configurazione json
Vedi doc.go per un esempio
Ho provato JSON. Ha funzionato. Ma odio dover creare la struttura dei campi e dei tipi esatti che potrei impostare. Per me è stato un dolore. Ho notato che era il metodo utilizzato da tutte le opzioni di configurazione che sono riuscito a trovare. Forse il mio background in linguaggi dinamici mi rende cieco ai benefici di tale verbosità. Ho creato un nuovo formato di file di configurazione semplice e una lib più dinamica per leggerlo.
https://github.com/chrisftw/ezconf
Sono abbastanza nuovo nel mondo Go, quindi potrebbe non essere il modo Go. Ma funziona, è abbastanza veloce e super semplice da usare.