如果 env var 为空,如何分配默认值?

如果在 Go 中没有设置环境变量,如何分配默认值?

在 Python 中,如果没有设置 MONGO_PASS env var,我可以执行 mongo_password = os.getenv('MONGO_PASS', 'pass'),其中 pass是默认值。

我尝试了一个基于 os.Getenv为空的 if 语句,但是由于 if 语句中变量赋值的作用域,这似乎不起作用。我正在检查多个 env 变量,所以我不能在 if 语句中处理这个信息。

97440 次浏览

There's no built-in to fall back to a default value, so you have to do a good old-fashioned if-else.

But you can always create a helper function to make that easier:

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

Note that as @michael-hausenblas pointed out in a comment, keep in mind that if the value of the environment variable is really empty, you will get the fallback value instead.

Even better as @ŁukaszWojciechowski pointed out, using os.LookupEnv:

func getEnv(key, fallback string) string {
if value, ok := os.LookupEnv(key); ok {
return value
}
return fallback
}

In case you are OK with adding little dependency you can use something like https://github.com/urfave/cli

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)
}

Go doesn't have the exact same functionality as Python here; the most idiomatic way to do it though, I can think of, is:

mongo_password := "pass"
if mp := os.Getenv("MONGO_PASS"); mp != "" {
mongo_password = mp
}

To have a clean code I do this:

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

I defined a function that is used in the whole app

// 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
}

What you're looking for is os.LookupEnv combined with an if statement.

Here is janos's answer updated to use LookupEnv:

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

Had the same question as the OP and found someone encapsulated the answers from this thread into a nifty library that is fairly simple to use, hope this help others!

https://github.com/caarlos0/env

For more complex application you can use tooling such as viper, which allows you to set global custom default values, parse configuration files, set a prefix for your app's env var keys (to ensure consistency and name spacing of env var configurations) and many other cool features.

Sample code:

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)
}

I also had the same problem and I just created a small package called getenvs exactly to answer this problem.

Getenvs supports string, bool, int and float and it can be used like below:

package main


import (
"fmt"


"gitlab.com/avarf/getenvs"
)


func main() {
value := getenvs.GetEnvString("STRING_GETENV", "default-string-value")
bvalue, _ := getenvs.GetEnvBool("BOOL_GETENV", false)
ivalue, _ := getenvs.GetEnvInt("INT_GETENV", 10)


fmt.Println(value)
fmt.Println(bvalue)
fmt.Println(ivalue)
}