Wie kann ich einen Standardwert zuweisen, wenn env var leer ist?

69

Wie weisen Sie einen Standardwert zu, wenn in Go keine Umgebungsvariable festgelegt ist?

In Python könnte ich tun, mongo_password = os.getenv('MONGO_PASS', 'pass')wo passder Standardwert ist, wenn MONGO_PASSenv var nicht gesetzt ist.

Ich habe eine if-Anweisung versucht, die darauf basiert os.Getenv, leer zu sein, aber das scheint aufgrund des Umfangs der Variablenzuweisung innerhalb einer if-Anweisung nicht zu funktionieren. Und ich suche nach mehreren env-Variablen, sodass ich in der if-Anweisung nicht auf diese Informationen reagieren kann.

Ryan Clair
quelle
4
An if funktioniert .
Volker
@Volker tut es? Ich habe es mit `` `mpass: = os.Getenv (" MONGO_PASS ") versucht, wenn len (mpass) == 0 {log.Println (" MONGO_PASS env var nicht gesetzt, mit mongo default ") mpass: =" pass "} `` `Und ich verstehe:./server.go:63: mpass declared and not used
Ryan Clair
Wobei Zeile 63 mit der Variablen mpass innerhalb des if-Blocks übereinstimmt (ich verwende mpass später).
Ryan Clair
Herausgefunden. Sollte wurden mit =statt :=auf die mpassin der ifErklärung. Danke, dass du mich Volker angerufen hast :-)
Ryan Clair

Antworten:

118

Es gibt keine eingebaute Funktion, um auf einen Standardwert zurückzugreifen. Sie müssen also ein gutes altmodisches If-else ausführen.

Sie können jedoch jederzeit eine Hilfsfunktion erstellen, um dies zu vereinfachen:

func getenv(key, fallback string) string {
    value := os.Getenv(key)
    if len(value) == 0 {
        return fallback
    }
    return value
}

Beachten Sie, dass Sie, wie @ michael-hausenblas in einem Kommentar hervorhob , bedenken, dass Sie stattdessen den Fallback-Wert erhalten, wenn der Wert der Umgebungsvariablen wirklich leer ist.

Noch besser, wie @ ŁukaszWojciechowski betonte os.LookupEnv:

func getEnv(key, fallback string) string {
    if value, ok := os.LookupEnv(key); ok {
        return value
    }
    return fallback
}
Janos
quelle
3
Beachten Sie, dass der obige Code zwar korrekt ist, Sie jedoch die Semantik kennen sollten: Da er die Länge der Zeichenfolge prüft valueund die leere Zeichenfolge ""die Länge 0 hat, bedeutet dies, dass Sie, wenn die env-Variable auf gesetzt ist, ""eher den Fallback- / Standardwert erhalten als der Wert (der trivial ist ""). Kommt wirklich auf deinen Anwendungsfall an, aber ich dachte, es lohnt sich darauf hinzuweisen, da ich einmal auf diesen semantischen Fehler
gestoßen bin
20
Anstelle von GetenvIhnen könnte verwenden LookupEnv. Es gibt auch den ok booleanStatus zurück, dass der Wert tatsächlich vorhanden war.
Łukasz Wojciechowski
36

Was Sie suchen, wird os.LookupEnvmit einer ifAussage kombiniert .

Hier ist die Antwort von Janos, die aktualisiert wurde, um LookupEnv zu verwenden:

func getEnv(key, fallback string) string {
    value, exists := os.LookupEnv(key)
    if !exists {
        value = fallback
    }
    return value
}
Puradox
quelle
13

Go hat hier nicht genau die gleiche Funktionalität wie Python. Der idiomatischste Weg, dies zu tun, ist:

mongo_password := "pass"
if mp := os.Getenv("MONGO_PASS"); mp != "" {
    mongo_password = mp
}
Michael Hausenblas
quelle
Danke für den Vorschlag Michael. Ich habe genau das versucht, was meinem ersten Versuch ähnlich war, und es beschwert sich, dass mongo_password innerhalb des if-Blocks nicht verwendet wird (der gleiche Fehler wie mein Kommentar zu Volker oben. Ich dachte, dies hat irgendwann damit zu tun, dass Variablen darin enthalten sind Ein if-Block war auf diesen Block beschränkt und konnte nicht nach draußen gelangen? Oder irre ich mich, und das sind deklarierte Variablen ... und mein Fehler ist darauf zurückzuführen, wie ich die Variable verwende?
Ryan Clair
1
Beachten Sie, dass die Zeile mongo_password := "pass"wichtig ist, da hiermit mongo_passworddeklariert und definiert wird ( passals Standardwert festgelegt). Wenn Sie diese Zeile nicht haben, kann ich mir einen Fehler vorstellen. In unserem obigen Fall hat nur mpder lokale Geltungsbereich des ifFWIW.
Michael Hausenblas
1
OHHHHHH. Glühbirne. Vielen Dank. Ich habe deklarieren (: =) und zuweisen (=) verwechselt. Funktioniert wie ein Champion. Du rockst Michael.
Ryan Clair
7

Um einen sauberen Code zu haben, mache ich Folgendes:

myVar := getEnv("MONGO_PASS", "default-pass")

Ich habe eine Funktion definiert, die in der gesamten App verwendet wird

// getEnv get key environment variable if exist otherwise return defalutValue
func getEnv(key, defaultValue string) string {
    value := os.Getenv(key)
    if len(value) == 0 {
        return defaultValue
    }
    return value
}
Eddy Hernandez
quelle
2

Hatte die gleiche Frage wie das OP und fand jemanden, der die Antworten aus diesem Thread in einer raffinierten Bibliothek zusammengefasst hat, die ziemlich einfach zu bedienen ist. Ich hoffe, dies hilft anderen!

https://github.com/caarlos0/env

Jaime Gago
quelle
Das ist Gold. Genau die elegante Lösung, die ich suchte
egoistisch
0

Wenn Sie mit dem Hinzufügen einer geringen Abhängigkeit einverstanden sind, können Sie beispielsweise https://github.com/urfave/cli verwenden

package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Flags = []cli.Flag {
    cli.StringFlag{
      Name: "lang, l",
      Value: "english",
      Usage: "language for the greeting",
      EnvVar: "APP_LANG",
    },
  }

  app.Run(os.Args)
}
Oleg Neumyvakin
quelle
0

Für komplexere Anwendungen können Sie Tools verwenden viper, mit denen Sie globale benutzerdefinierte Standardwerte festlegen, Konfigurationsdateien analysieren, ein Präfix für die env var-Schlüssel Ihrer App festlegen (um die Konsistenz und den Namensabstand der env var-Konfigurationen sicherzustellen) und viele andere coole Funktionen verwenden können Eigenschaften.

Beispielcode:

package main

import (
    "fmt"

    "github.com/spf13/viper"
)

func main() {
    viper.AutomaticEnv() // read value ENV variable
    // Set default value
    viper.SetEnvPrefix("app")
    viper.SetDefault("linetoken", "DefaultLineTokenValue")

    // Declare var
    linetoken := viper.GetString("linetoken")

    fmt.Println("---------- Example ----------")
    fmt.Println("linetoken :", linetoken)
}
Stanislav
quelle