management - Cómo manejar la configuración en Go
properties golang (13)
Comencé a usar Gcfg que usa archivos similares a Ini. Es simple: si quieres algo simple, esta es una buena opción.
Aquí está el código de carga que estoy usando actualmente, que tiene configuraciones predeterminadas y permite marcas de línea de comando (no mostradas) que anulan algunas de mis configuraciones:
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
}
Soy nuevo en la programación de Go, y me pregunto: ¿cuál es la forma preferida de manejar los parámetros de configuración para un programa Go (el tipo de cosas para las que se pueden usar archivos de propiedades o archivos ini , en otros contextos)?
El formato JSON me funcionó bastante bien. La biblioteca estándar ofrece métodos para escribir la estructura de datos con sangría, por lo que es bastante legible.
Véase también este hilo de golang-nuts .
Los beneficios de JSON son que es bastante simple de analizar y legible / editable por humanos, a la vez que ofrece semánticas para listas y asignaciones (que pueden ser bastante útiles), lo que no es el caso de muchos analizadores de configuración de tipo ini.
Ejemplo de uso:
conf.json :
{
"Users": ["UserA","UserB"],
"Groups": ["GroupA"]
}
Programa para leer la configuración.
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]
Escribí una simple biblioteca de configuración ini en golang.
Goroutine-Safe, 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)
}
}
=================== Actualizar =======================
Recientemente necesito un analizador INI con soporte de sección, y escribo un paquete simple:
github.com/c4pt0r/cfg
Puedes analizar el INI como usar el paquete "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)
}
Estoy de acuerdo con y escribí una pequeña herramienta para que todo fuera realmente fácil.
bitbucket.org/gotamer/cfg es un paquete de configuración json
- Usted define sus elementos de configuración en su aplicación como una estructura.
- Una plantilla de archivo de configuración json de su estructura se guarda en la primera ejecución
- Puede guardar modificaciones de tiempo de ejecución a la configuración
Ver doc.go para un ejemplo
Otra opción es usar TOML , que es un formato similar a INI creado por Tom Preston-Werner. Construí un analizador Go para él que está ampliamente probado . Puedes usarlo como otras opciones propuestas aquí. Por ejemplo, si tiene estos datos TOML en algo.toml
Age = 198
Cats = [ "Cauchy", "Plato" ]
Pi = 3.14
Perfection = [ 6, 28, 496, 8128 ]
DOB = 1987-07-05T05:45:00Z
Luego puedes cargarlo en tu programa Go con 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
}
Probé con JSON. Funcionó. Pero odio tener que crear la estructura de los campos y tipos exactos que podría estar configurando. Para mí eso fue un dolor. Noté que era el método usado por todas las opciones de configuración que pude encontrar. Tal vez mi experiencia en lenguajes dinámicos me hace ciego a los beneficios de tal verbosidad. Hice un nuevo formato de archivo de configuración simple y una biblioteca más dinámica para leerlo.
https://github.com/chrisftw/ezconf
Soy bastante nuevo en el mundo Go, por lo que podría no ser el camino Go. Pero funciona, es bastante rápido y muy fácil de usar.
Pros
- Super simple
- Menos codigo
Contras
- No hay matrices o tipos de mapas
- Formato de archivo muy plano.
- Archivos conf no estándar
- Tiene una pequeña convención incorporada, la cual ahora estoy mal visto en general en la comunidad Go. (Busca el archivo de configuración en el directorio de configuración)
Sólo usa banderas de go estándar con iniflags .
Las banderas estándar tienen los siguientes beneficios:
- Idiomático.
- Fácil de usar. Las banderas se pueden agregar y dispersar fácilmente en paquetes arbitrarios que usa su proyecto.
- Los indicadores tienen compatibilidad inmediata con los valores y la descripción predeterminados.
- Los indicadores proporcionan una salida de ''ayuda'' estándar con valores y descripción predeterminados.
El único inconveniente que tienen las banderas go go - es problemas de administración cuando el número de banderas utilizadas en su aplicación es demasiado grande.
Iniflags resuelve elegantemente este problema: simplemente modifique dos líneas en su paquete principal y mágicamente obtiene soporte para leer valores de marca de archivo ini. Los indicadores de los archivos ini se pueden anular pasando nuevos valores en la línea de comandos.
Consulte también https://groups.google.com/forum/#!topic/golang-nuts/TByzyPgoAQE para obtener más información.
También te puede interesar go-libucl , un conjunto de enlaces Go para UCL, el lenguaje de configuración universal. UCL es un poco como JSON, pero con un mejor soporte para humanos: admite comentarios y construcciones legibles para el ser humano como los multiplicadores SI (10k, 40M, etc.) y tiene un poco menos de repetición (por ejemplo, citas alrededor de las teclas). En realidad, está bastante cerca del formato de archivo de configuración nginx, si ya está familiarizado con eso.
Usa toml como este artículo Leyendo los archivos de configuración por el camino.
Usualmente uso JSON para estructuras de datos más complicadas. La desventaja es que fácilmente terminas con un montón de código para decirle al usuario dónde estuvo el error, varios casos de borde y qué no.
Para la configuración básica (claves api, números de puerto, ...) he tenido muy buena suerte con el paquete gcfg . Se basa en el formato git config.
De la documentación:
Configuración de muestra:
; Comment line
[section]
name = value # Another comment
flag # implicit value for bool is true
Ir estructura:
type Config struct {
Section struct {
Name string
Flag bool
}
}
Y el código necesario para leerlo:
var cfg Config
err := gcfg.ReadFileInto(&cfg, "myconfig.gcfg")
También admite valores de sector, por lo que puede permitir especificar una clave varias veces y otras características interesantes como esa.
echar un vistazo 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)
Viper y https://github.com/zpatrick/go-config son bibliotecas bastante buenas para archivos de configuración.
Viper es un sistema de administración de configuración de Golang que funciona con JSON, YAML y TOML. Parece bastante interesante.