开发者

获取Golang环境变量的三种方式小结

目录
  • 环境变量和配置文件
  • 使用Viper包从配置文件中读环境变量
    • 示例1
    • 示例2
  • 使用GoDotEnv包从配置文件中读环境变量
    • 使用os包从配置文件中读环境变量
      • 使用os.Setenv()设置环境变量
      • 使用os.Getenv()读系统环境变量
      • 使用os.LookupEnv()读系统环境变量
      • 使用os.UnsetEvn()取消设置环境变量
    • 总结

      环境变量是应用软件参数配置的最佳方式,可以定义系统级,如开发、测试以及生成阶段。配置参数主要有数据库配置、第三方url等。因此环境变量对于开发和部署应用至关重要。

      环境变量和配置文件

      shell 编程中从文件读变量相对容易,只需要source包括环境变量的配置文件,就可以访问所有这些变量。golang必须依赖一些模块从文件中读变量。本文内容包括:

      • 如何通过文件声明环境变量
      • 如何从文件读取环境变量
      • 当变量未定义或空,如何设置缺省值
      • 如果从系统读取环境变量
      • 如何检查环境变量被定义或非空

      当容器化部署应用(cloud, Kubernetes, 或docker)至测试和生产环境时,环境变量角色非常重要,它可以很容易覆盖缺省配置。golang访问环境变量常用方法有三种:

      • Viper 包
      • godotenv 包
      • os 包

      我们在示例项目中创建配置文件app.env文件,用于设置预定环境变量的缺省值。

      创建环境变量配置文件必须遵守一些规则,否则golang可能不会识别变量值:

      所有变量必须在单独行中声明

      区分大小写的变量名应该使用大写命名,单词应该用下划线分隔,举例:DB_HOST

      变量值跟在变量名称后面使用等号分割,举例:DB_HOST=localhost

      变量值不用双引号,举例: DB_HOST=”localhost”

      注释不应该与变量在一行,举例:

      # depends with database ports mysql,MongoDB,postgres etc
      DB_PORT=5432
      

      举例,app.env 文件:

      # sample app.env
      # environment can be test,production,testing
      APP_ENV=development
      # username
      DB_USER=postgres
      # secure password
      DB_PASS=pass
      # app version not set
      APP_VERSION=
      #listening to any address
      SERVER_ADDRESS=0.0.0.0:8080
      # host value
      DB_HOST=localhost
      #depends with database mysql,mongodb,postgres etc
      DB_PORT=5432
      

      使用Viper包从配置文件中读环境变量

      这是一个环境变量管理工具包,可以从环境变量或配置文件中读变量值。通过下面命令安装包:

      go get github.com/spf13/viper
      

      示例1

      首先定义结构体,用于全局保存配置文件中的环境变量。

      type Config struct {
      	AppEnv        string `mapstructure:"APP_ENV"`
      	DBUser        string `mapstructure:"DB_USER"`
      	DBPass        string `mapstructure:"DB_PASS"`
      	DBHost        string `mapstructure:"DB_HOST"`
      	DBPort        string `mapstructure:"编程DB_PORT"`
      	DBDriver      string `mapstructure:"DB_DRIVER"`
      	AppVersion    string `mapstructure:"APP_VERSION"`
      	ServerAddress string `mapstructure:"SERVER_ADDRESS"`
      }
      

      下面定义函数加载配置文件:

      func LoadConfig(path string) (config Config, err error) {
      	// Read file path
      	viper.AddConfigPath(path)
      
      	// set config file and path
      	viper.SetConfi编程客栈gName("app")
      	viper.SetConfigType("env")
      
      	// watching changes in app.env
      	viper.AutomaticEnv()
      
      	// reading the config file
      	err = viper.ReadInConfig()
      	if err != nil {
      		return
      	}
      
      	err = viper.Unmarshal(&config)
      	return
      }
      

      完整代码如下:

      package main
      
      import (
      	"fmt"
      	"log"
      
      	"github.com/spf13/viper"
      )
      
      // Config stores all configuration of the application.
      // The values are read by viper from a config file or environment variable.
      type Config struct {
      	AppEnv        string `mapstructure:"APP_ENV"`
      	DBUser        string `mapstructure:"DB_USER"`
      	DBPass        string `mapstructure:"DB_PASS"`
      	DBHost        string `mapstructure:"DB_HOST"`
      	DBPort        string `mapstructure:"DB_PORT"`
      	DBDriver      string `mapstructure:"DB_DRIVER"`
      	AppVersion    string `mapstructure:"APP_VERSION"`
      	ServerAddress string `mapstructure:"SERVER_ADDRESS"`
      }
      
      // LoadConfig reads configuration from file or environment variables.
      func LoadConfig(path string) (config Config, err error) {
      	// Read file path
      	viper.AddConfigPath(path)
      	// set config file and path
      	viper.SetConfigName("app")
      	viper.SetConfigType("env")
      	// watching changes in app.env
      	viper.AutomaticEnv()
      	// reading the config file
      	err = viper.ReadInConfig()
      	if err != nil {
      		return
      	}
      
      	err = viper.Unmarshal(&config)
      	return
      }
      
      func main() {
      	// load app.env file data to struct
      	config, err := LoadConfig("."js)
      
      	// handle errors
      	if err != nil {
      		log.Fatalf("can't load environment app.env: %v", err)
      	}
      
      	fmt.Printf(" -----%s----\n", "Reading Environment variables Using Viper package")
      	fmt.Printf(" %s = %v \n", "Application_Environment", config.AppEnv)
      	// not defined
      	fmt.Printf(" %s = %s \n", "DB_DRIVE", dbDrive)
      	fmt.Printf(" %s = %s \n", "Server_Listening_Address", config.ServerAddress)
      	fmt.Printf(" %s = %s \n", "Database_User_Name", config.DBUser)
      	fmt.Printf(" %s = %s \n", "Database_User_Password", config.DBPass)
      
      }
      

      输出结果:

      $ go run main.go
       ------Reading Environment variables Using Viper package----------
       Application_Environment = development 
       Server_Listening_Address = 0.0.0.0:8080 
       Database_User_Name = postgres 
       Database_User_Password = pass
      

      示例2

      有时环境变量可能未设置,这样代码可能会出错,我们可以使用下面方法定义缺省值:

      viper.SetDefault:

      下面示例代码定义函数,如果变量未空或未定义,则返回缺省值:

      package main
      
      import (
      	"fmt"
      
      	"github.com/spf13/viper"
      )
      
      //Function to read an envIiclyaironment or return a default value
      func getEnvValue(key string, defaultValue string) string {
      
      	// Get file path
      	viper.SetConfigFile("app.env")
      	//read configs and handle errors
      	err := viper.ReadInConfig()
      	if err != nil {
      		fmt.Println(err)
      	}
      	value := viper.GetString(key)
      	if value != "" {
      		return value
      	}
      	return defaultValue
      }
      func main() {
      	// reading environments variable using the viper
      	appEnv := getEnvValue("APP_ENV", "defaultEnvtesting")
      	// not set in our app.env
      	appVersion := getEnvValue("APP_VERSION", "1")
      	dbPass := getEnvValue("DB_PASS", "1234")
      	dbUser := getEnvValue("DB_USER", "golinux_DB")
      	serverAddress := getEnvValue("SERVER_ADDRESS", "127.0.0.1:8080")
      
      	fmt.Printf(" ------%s-----\n", "Reading Environment variables Using Viper package")
      	fmt.Printf(" %s = %s \n", "Application_Environment", appEnv)
      	fmt.Printf(" %s = %s \n", "Application_Version", appVersion)
      	fmt.Printf(" %s = %s \n", "Server_Listening_Address", serverAddress)
      	fmt.Printf(" %s = %s \n", "Database_User_Name", dbUser)
      	fmt.Printf(" %s = %s \n", "Database_User_Password", dbPass)
      }
      

      输出结果:

      $ go run main.go
       ---Reading Environment variables Using Viper package--------
       Application_Environment = development 
       Application_Version = 1 
       Server_Listening_Address = 0.0.0.0:8080 
       Database_User_Name = postgres 
       Database_User_Password = pass
      

      使用GoDotEnv包从配置文件中读环境变量

      GoDotEnv包功能与viper包类似,但使用godotenv.Load()函数加载app.env文件,它接收文件名作为输入,返回应用上下文中的值。实现下php面命令安装包:

       go get github.com/joho/godotenv
      

      Load方法可以传入文件名称,举例:godotenv.Load("app.env")

      有时.env文件位于项目根目录,则可以直接载入,无需传入参数:godotenv.Load("app.env)godotenv还支持一次加载多个配置文件:

      _ = godotenv.Load("app.env", "k8s_app.env")
      

      并且还支持YAML文件作为输入:

      // app.YAML
      APP_ENV: Development
      SERVER_ADDRESS: 0.0.0.0:8080
      

      下面看一个完整实例:

      // main.go
      package main
      
      import (
      	"fmt"
      	"log"
      	"os"
      
      	"github.com/joho/godotenv"
      )
      
      // Function to read an environment or return a default value
      func getEnvValue(key string, defaultValue string) string {
      	if value, ok := os.LookupEnv(key); ok && value != "" {
      		return value
      	}
      	return defaultValue
      }
      
      func main() {
      	// load app.env file
      	err := godotenv.Load("app.env")
      	//handle errors
      	if err != nil {
      		log.Fatalf("can't load environment app.env: %v", err)
      	}
      
      	// reading environments variable from the app context
      	appEnv := getEnvValue("APP_ENV", "defaultEnvtesting")
      
      	// not defined in our app.env
      	appVersion := getEnvValue("APP_VERSION", "1")
      	dbPass := getEnvValue("DB_PASS", "1234")
      
      	// DB_NAME not defined in app env
      	dbName := getEnvValue("DB_NAME", "goLinux_DB")
      	dbUser := getEnvValue("DB_USER", "goLinux_DB")
      	serverAddress := getEnvValue("SERVER_ADDRESS", "127.0.0.1:8080")
      
      	fmt.Printf(" ----%s---\n", "Reading Environment variables Using GoDotEnv package ")
      	fmt.Printf(" %s = %s \n", "Application_Environment", appEnv)
      	fmt.Printf(" %s = %s \n", "Application_Version", appVersion)
      	fmt.Printf(" %s = %s \n", "Server_Listening_Address", serverAddress)
      	fmt.Printf(" %s = %s \n", "Database_User_Name", dbUser)
      	fmt.Printf(" %s = %s \n", "Database_User_Password", dbPass)
      	fmt.Printf(" %s = %s \n", "Database_Name", dbName)
      
      }
      

      输出结果:

      $ go run main.go   
                    
       -----Reading Environment variables Using GoDotEnv package-----
       Application_Environment = development 
       Application_Version = 1 
       Server_Listening_Address = 0.0.0.0:8080 
       Database_User_Name = postgres 
       Database_User_Password = pass 
       Database_Name = goLinux_DB
      

      使用os包从配置文件中读环境变量

      使用os.Setenv()设置环境变量

      os.Setenv(key,value) 接收两个输入参数,一个为key,另一个是环境变量值。

      语法如下:

      err := os.Setenv(key, value)
      if err != nil {
      	fmt.Printf("error will setting the environment value: %s", err)
      }
      

      举例,设置COLOUR=BLUE:

      err := os.Setenv(COLOUR, BLUE)
      if err != nil {
      	fmt.Printf("error will setting the environment value: %s", err)
      }
      

      使用os.Getenv()读系统环境变量

      os.Getenv接收key,举例,下面代码获取环境变量PATH的值:

      // main.go
      package main
      
      import (
      	"fmt"
      	"os"
      )
      
      func main() {
      	fmt.Println("supported paths in my shell: ", os.Getenv("PATH"))
      }
      

      使用os.LookupEnv()读系统环境变量

      os.Getenv()的缺点是无错误返回key。对于需要增加额外检查是否存在,则需要使用os.LookupEnv(),其返回值中包括布尔变量用于表示key是否存在。举例:

      // main.go
      package main
      
      import (
      	"fmt"
      	"log"
      	"os"
      )
      
      func main() {
      
      	path, ok := os.LookupEnv("PATH123")
      	if !ok {
      		log.Fatalln(path + " variable is not defined")
      	}
      	fmt.Println(path)
      }
      

      使用os.UnsetEvn()取消设置环境变量

      os.UnsetEvn() 删除或取消定义任何系统环境变量。注意,这只会暂时取消当前终端的变量设置。举例:

      // main.go
      package main
      
      import (
      	"fmt"
      	"os"
      )
      
      func main() {
      	
      	os.Setenv("MYUSER", "TestUser")
      	// Before unsetting the variable
      	out, _ := os.LookupEnv("MYUSER")
      	fmt.Println("BEFORE: " + out)
      
      	// Unset the variable
      	os.Unsetenv("MYUSER")
      
      	// After unsetting the variable
      	out, _ = os.LookupEnv("MYUSER")
      	fmt.Println("AFTER: " + out)
      }
      

      总结

      到此这篇关于获取Golang环境变量的三种方式小结的文章就介绍到这了,更多相关Golang获取环境变量内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新开发

      开发排行榜