Viper
Repository-Adresse: spf13/viper: Go configuration with fangs (github.com)
Dokumentations-Adresse: spf13/viper: Go configuration with fangs (github.com)
TIP
Die offizielle Seite diskutiert derzeit den Übergang zu Viper2. Weitere Informationen finden Sie unter: Viper2
Installation
go get github.com/spf13/viperEinführung
Viper ist eine vollständige Konfigurationsdatei-Lösung für Go-Anwendungen. Es kann fast alle Arten von Konfigurationsanforderungen und -formaten verarbeiten und erleichtert die Verwaltung von Projektkonfigurationsdateien. Es verfügt über folgende Funktionen:
- Standardwerteinstellung
- Unterstützte Formate: JSON, TOML, YAML, HCL, envfile, Java properties
- Echtzeit-Überwachung und Neuladen von Konfigurationsdateien
- Lesen aus Umgebungsvariablen
- Lesen von Konfigurationen aus Remote-Konfigurationssystemen und Überwachen von Änderungen
- Lesen von Kommandozeilen-Flags
- Lesen aus Puffern
- Explizites Setzen von Werten
Offiziell behauptet Viper, alle Anforderungen an Anwendungskonfigurationen erfüllen zu können. Entwickler müssen sich nur auf den Bau der Anwendung konzentrieren, während Viper die Konfigurationsverwaltung übernimmt. Viele bekannte Projekte verwenden Viper:
DANGER
Viper ist nicht für die Ver- und Entschlüsselung von Konfigurationsdateien verantwortlich, d.h. es führt keine Sicherheitsbehandlungen für Konfigurationsdateien durch.
Lesereihenfolge
Viper verwendet folgende Priorität zum Lesen der Konfiguration:
- Explizit gesetzte Werte
- Kommandozeilen-Flags
- Umgebungsvariablen
- Konfigurationsdateien
- Schlüsselwert-Speicher
- Standardwerte
TIP
Die Schlüssel in der Viper-Konfiguration unterscheiden nicht zwischen Groß- und Kleinschreibung. In zukünftigen Diskussionen könnte dies optional gemacht werden.
Standardwerte
Ein gutes Konfigurationssystem sollte die Einstellung von Standardwerten unterstützen. Obwohl dies nicht immer notwendig ist, ist es sehr nützlich, wenn keine Konfigurationsdatei gesetzt ist. Hier ist ein Beispiel:
viper.SetDefault("filePath","./dir/img/usr")
viper.SetDefault("root","123456")Lesen von Konfigurationsdateien
Viper benötigt nur sehr wenig Konfiguration, um zu wissen, wo nach Konfigurationsdateien gesucht werden soll. Viper unterstützt JSON-, TOML-, YAML-, HCL-, INI-, envfile- und JavaProperties-Dateien. Viper kann mehrere Pfade gleichzeitig durchsuchen, aber derzeit unterstützt eine einzelne Viper-Instanz nur eine einzelne Konfigurationsdatei. Viper setzt keinen Standardpfad für die Konfigurationssuche und überlässt die Standardentscheidung der Anwendung.
Hier ist ein Beispiel für die Verwendung von Viper zum Lesen einer Konfigurationsdatei. Es ist nicht notwendig, einen vollständigen Pfad anzugeben, aber beim Verwenden sollte mindestens eine Konfigurationsdatei bereitgestellt werden.
func TestReadConfigFile(t *testing.T) {
viper.SetConfigName("config.yml") // Liest eine Konfigurationsdatei namens config, ohne bestimmte Dateierweiterung
viper.SetConfigType("yaml") // Wenn keine bestimmte Dateierweiterung gesetzt ist, muss der Dateityp angegeben werden
viper.AddConfigPath("./") // Suche im aktuellen Ordner
viper.AddConfigPath("$HOME/") // Verwende Variable
viper.AddConfigPath(".") // Suche im Arbeitsverzeichnis
err := viper.ReadInConfig() // Konfiguration lesen
if err != nil {
log.Fatalln(err)
}
}Es kann auch separat der Fall behandelt werden, dass die Konfigurationsdatei nicht gefunden wurde:
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// Konfigurationsdatei nicht gefunden
} else {
// Andere Arten von Fehlern
}
}Hier sind alle Funktionen zum Zugriff auf die Konfiguration:
Get(key string) : interface{}GetBool(key string) : boolGetFloat64(key string) : float64GetInt(key string) : intGetIntSlice(key string) : []intGetString(key string) : stringGetStringMap(key string) : map[string]interface{}GetStringMapString(key string) : map[string]stringGetStringSlice(key string) : []stringGetTime(key string) : time.TimeGetDuration(key string) : time.DurationIsSet(key string) : boolAllSettings() : map[string]interface{}
Beim Zugriff auf verschachtelte Konfigurationen wird der .-Trennzeichen verwendet, zum Beispiel:
{
"server":{
"database":{
"url": "mysql...."
}
}
}Kann über GetString("server.database.url") auf die Verschachtelung zugegriffen werden.
Schreiben von Konfigurationsdateien
Viper bietet eine Reihe von Funktionen, um Entwicklern das Schreiben von Laufzeitkonfigurationen in Konfigurationsdateien zu erleichtern.
// WriteConfig schreibt die Konfiguration in die ursprüngliche Konfigurationsdatei, Fehler wenn nicht vorhanden, überschreibt wenn vorhanden
func WriteConfig() error { return v.WriteConfig() }
// SafeWriteConfig schreibt die Konfiguration sicher in die ursprüngliche Konfigurationsdatei, erstellt wenn nicht vorhanden, überschreibt nicht wenn vorhanden
func SafeWriteConfig() error { return v.SafeWriteConfig() }
// WriteConfigAs schreibt die aktuelle Konfiguration in die angegebene Datei, Fehler wenn Datei nicht vorhanden, überschreibt wenn vorhanden
func WriteConfigAs(filename string) error { return v.WriteConfigAs(filename) }
// SafeWriteConfigAs Wenn die angegebene Datei existiert, wird die ursprüngliche Konfigurationsdatei nicht überschrieben, gibt Fehler zurück wenn Datei existiert
func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) }Hier sind einige Beispiele:
func TestWritingConfig(t *testing.T) {
viper.WriteConfig() // Schreibt Konfiguration in die ursprüngliche Konfigurationsdatei, diese sollten zuvor durch 'viper.AddConfigPath()' und 'viper.SetConfigName' definiert sein
viper.SafeWriteConfig()
viper.WriteConfigAs("/path/to/my/.config")
viper.SafeWriteConfigAs("/path/to/my/.config") // Gibt Fehler zurück, da die angegebene Datei existiert
viper.SafeWriteConfigAs("/path/to/my/.other_config")
}Überwachung und Neuladen der Konfiguration
Viper ermöglicht es Anwendungen, zur Laufzeit dynamisch eine Konfigurationsdatei zu lesen, d.h. ohne Neustart der Anwendung werden aktualisierte Konfigurationen wirksam, ohne ein einziges Änderungsdetail zu verpassen. Sie müssen lediglich der Viper-Instanz mitteilen, die Konfigurationsänderungen zu überwachen, oder Sie können eine Funktion bereitstellen, die bei jeder Änderung ausgeführt wird.
func TestWatchingConfig(t *testing.T) {
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Konfigurationsdatei wurde geändert:", e.Name)
})
viper.WatchConfig()
}Aliase
func TestAliases(t *testing.T) {
viper.RegisterAlias("a", "b")
viper.Set("a", 1)
viper.Set("b", 2) // Wird die Konfiguration von a überschreiben
fmt.Println(viper.GetInt("a"))
}Extrahieren von Unterstrukturen
Zuvor wurde erwähnt, dass über den .-Trennzeichen auf verschachtelte Konfigurationen zugegriffen werden kann. Tatsächlich kann auch die Funktion viper.Sub() verwendet werden, um Unterstrukturen zu extrahieren. Der Rückgabewert ist eine Viper-Instanz, wie im folgenden Beispiel:
cache:
cache1:
max-items: 100
item-size: 64
cache2:
max-items: 200
item-size: 80cache1Config := viper.Sub("cache.cache1")
if cache1Config == nil { // Gibt nil zurück wenn nicht vorhanden
panic("cache1 Konfiguration existiert nicht")
}Festlegen des Verschachtelungstrennzeichens
Wenn der angegebene Schlüssel . enthält, muss ein anderes Trennzeichen manuell festgelegt werden, um Fehlinterpretationen zu vermeiden, zum Beispiel:
viper.KeyDelimiter("/") // Setzt das Trennzeichen auf /Deserialisierung
Viper bietet zwei Funktionen, um die Konfiguration in eine Struktur oder Map zu deserialisieren, was ebenfalls verschachtelte Strukturen unterstützt:
Unmarshal(rawVal interface{}) : errorUnmarshalKey(key string, rawVal interface{}) : error
type config struct {
Port int
Name string
PathMap string `mapstructure:"path_map"`
}
var C config
err := viper.Unmarshal(&C)
if err != nil {
t.Fatalf("Kann nicht in Struktur deserialisieren, %v", err)
}Serialisierung
Serialisiert die aktuelle Konfiguration in einen String in einem bestimmten Format, um sie in einer Konfigurationsdatei zu speichern. Normalerweise werden JSON, TOML, YAML, HCL, envfile und Java properties unterstützt.
TIP
Viper unterstützt auch benutzerdefinierte Serialisierungsformate: Decoding custom formats with Viper - Márk Sági-Kazár (sagikazarmark.hu)
import (
yaml "gopkg.in/yaml.v2"
// ...
)
func yamlStringSettings() string {
c := viper.AllSettings()
bs, err := yaml.Marshal(c)
if err != nil {
log.Fatalf("Kann Konfiguration nicht als YAML serialisieren: %v", err)
}
return string(bs)
}Mehrere Instanzen
Normalerweise reicht die von Viper bereitgestellte globale Instanz aus. Da jedoch eine Instanz nur eine Konfigurationsdatei abbilden kann, können Sie mehrere Instanzen selbst erstellen, um weitere Operationen durchzuführen, zum Beispiel:
x := viper.New()
y := viper.New()
x.SetDefault("ContentDir", "content")
y.SetDefault("ContentDir", "foobar")
//...