环境变量是应用软件参数配置的最佳方式,可以定义系统级,如开发、测试以及生成阶段。配置参数主要有数据库配置、第三方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 pathviper.AddConfigPath(path)// set config file and pathviper.SetConfigName("app")viper.SetConfigType("env")// watching changes in app.envviper.AutomaticEnv()// reading the config fileerr = viper.ReadInConfig()if err != nil {return}err = viper.Unmarshal(&config)return
}

完整代码如下:

package mainimport ("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 pathviper.AddConfigPath(path)// set config file and pathviper.SetConfigName("app")viper.SetConfigType("env")// watching changes in app.envviper.AutomaticEnv()// reading the config fileerr = viper.ReadInConfig()if err != nil {return}err = viper.Unmarshal(&config)return
}func main() {// load app.env file data to structconfig, err := LoadConfig(".")// handle errorsif 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 definedfmt.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 mainimport ("fmt""github.com/spf13/viper"
)//Function to read an environment or return a default value
func getEnvValue(key string, defaultValue string) string {// Get file pathviper.SetConfigFile("app.env")//read configs and handle errorserr := 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 viperappEnv := getEnvValue("APP_ENV", "defaultEnvtesting")// not set in our app.envappVersion := 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文件,它接收文件名作为输入,返回应用上下文中的值。实现下面命令安装包:

 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 mainimport ("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 fileerr := godotenv.Load("app.env")//handle errorsif err != nil {log.Fatalf("can't load environment app.env: %v", err)}// reading environments variable from the app contextappEnv := getEnvValue("APP_ENV", "defaultEnvtesting")// not defined in our app.envappVersion := getEnvValue("APP_VERSION", "1")dbPass := getEnvValue("DB_PASS", "1234")// DB_NAME not defined in app envdbName := 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 mainimport ("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 mainimport ("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 mainimport ("fmt""os"
)func main() {os.Setenv("MYUSER", "TestUser")// Before unsetting the variableout, _ := os.LookupEnv("MYUSER")fmt.Println("BEFORE: " + out)// Unset the variableos.Unsetenv("MYUSER")// After unsetting the variableout, _ = os.LookupEnv("MYUSER")fmt.Println("AFTER: " + out)
}

总结

本文介绍了使用viper,godotenv 和 os包操作环境变量,同时提供相应的示例,希望对你有帮助。

获取Golang环境变量的三种方式相关推荐

  1. js声明变量的三种方式

    JS 声明变量的三种方式 (1)使用变量步骤:a.声明-->b.赋值-->3.调用 正确用法: <script type="text/javascript"> ...

  2. Win10设置环境变量的5种方式,在哪打开? 如何打开?

    本文目录 前言 一.运行 - 从系统属性入手 二.运行 - 直接打开 三.搜索 - env 四.我的电脑右键-属性,打开设置 五.控制面板-搜索env 前言 本文主要介绍:Win10设置环境变量的5种 ...

  3. Kettle中设置环境变量的几种方式

    下面是设置环境变量的四种方式: 1.设置变量步骤 2. 通过属性文件(常用) 在C:\Users${userName}.kettle\kettle.properties 中添加变量(key=value ...

  4. 设置环境变量的三种方法【转载】

    文章目录 1 设置环境变量的三种方法 1.1 临时设置 1.2 当前用户的全局设置 1.3 所有用户的全局设置 2 测试当前环境变量 3 脚本解析 3.1 打开的文件如下: 3.2 脚本解析说明 3. ...

  5. Unity3D获取游戏对象组件的三种方式

    Unity获取游戏对象组件的三种方式 用Find查询 1. GameObejct go = GameObject.Find("对象名").GetComponent<获取对象上 ...

  6. Action 中获取表单数据的三种方式

    (尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/53138905  冷血之心的博客) Action 中获取表单提交数据 ...

  7. 获取Class类对象的三种方式

    三种方式分类 类名.class属性 对象名.getClass()方法 Class.forName(全类名)方法 示例代码 public class ReflectDemo {public static ...

  8. 定义结构体变量的三种方式

    #include <stdio.h>//定义结构体的三种方式,推荐使用第三种//第一种 struct student1 {int age;char name[20];float score ...

  9. 获取class文件对象的三种方式

    package cn.learn_01;/** 反射:就是通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法.* * Person p = new Person();* p.使用* ...

最新文章

  1. php 获取class id,CSS Class 與 CSS ID
  2. 2020-06-15 有理分式矩阵及其互质分解
  3. 误删除了_msdcs.domain.com
  4. mysql-connector-java.jar乱码_jdbc连接数据库,中文出现乱码的问题
  5. cocos2d-x游戏实例(3)-获得地图索引
  6. http 请求(tomcat) 返回 错误页面信息
  7. java 事务的提出者_java中什么是事务
  8. 微信公众号开发 重要 access_token {errcode:40164,errmsg:invalid ip 114.221.159.11, not in whitelist hint:
  9. readfile函数使用方法_1分钟学会LOOKUP函数,有网友说使用这个方法,初学者秒变大神...
  10. c语言可以利用数组处理批量数据库,C语言程序设计 利用数组处理批量数据.ppt...
  11. Apollo(阿波罗)是携程框架部门研发的分布式配置中心,ubuntu本机安装
  12. Kali linux 2016.2(Rolling)中的Exploits模块详解
  13. 易撰微信编辑器使用指南!
  14. 基于STM32MP1的IOT参考设计(采用QT和web技术)
  15. ABAQUS常见错误(一)多根预应力钢绞线
  16. 钉钉机器人给指定人发消息
  17. JAVA后端开发必备软件(仅供参考)
  18. uniapp调试ESC指令热敏打印机 打印图片 以及 打印途中报10007特性不支持解决方案
  19. base64转成文件
  20. 用 Python 解释 SpaceX 如何进行火箭回收

热门文章

  1. bottom sheets_Excel 2013中的SHEET和SHEETS函数
  2. 一周内,被闲鱼疯转2.6W次,最终被所有平台封杀!
  3. python 中文转拼音原理_Python中文转拼音
  4. Zmeet云雾架构-融合AI能力的通讯层的变革,性能远超传统通讯技术
  5. 数据库 vs 数据仓库
  6. 信用卡如何使用?广发卡自动分期教你这样养卡技巧
  7. 公司注册地址可以随便写吗,如何注册企业工商营业执照
  8. 视频去水印工具有什么 哪个去水印软件好用
  9. 磁力搜索网站+下载神器放送2019-03-05
  10. 自签发SSL证书签发生成过程