环境变量是应用软件参数配置的最佳方式,可以定义系统级,如开发、测试以及生成阶段。配置参数主要有数据库配置、第三方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.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
}
完整代码如下:
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(".")
// 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 environment 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文件,它接收文件名作为输入,返回应用上下文中的值。实现下面命令安装包:
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获取环境变量内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论