器 | Go四种方式读取环境配置文件


theme: jzman

「本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!

配置文件在一个项目中至关重要,如何高效的读取配置尤为关键。如果不采用任何三方库,最常用的方式是通过文件I/O获取文件的内容,但我毕竟只是想要读取个配置文件,这还要进行文件操作,未免有些造轮子了。而且,文件的格式多种多样,如何格式的读取文件内容和根据不同的环境读取也是一个不小的挑战。这篇文章我介绍四种读取配置文件的方式,请按照各自的需求选择。

一、四种读取方式简介

比较出众的有两种,包括ViperGoDotEnv,这两种方式受众相当的广泛,ViperGithub的star最多,文档更加全面,GoDotEnv次之。另外还有两个比较小众轻量级的,包括gonfiggo-akka。分别的介绍请参考Github介绍。

go-akka

Currently Not Available !!!

Github传送带

godotenv(Available)

A Go (golang) port of the Ruby dotenv project (which loads env vars from a .env file)

Github传送带

gonfig

gonfig is a lightweight Golang package for intergrating both JSON configs and enviornment variables into one config object.

Github传送带

viper(Available,Most stars)

Viper is heading towards v2 and we would love to hear what you would like to see in it.

Github传送带

二、go-akka实践

配置文件config.yaml

port: 8081 debug: true

解析配置config.go

import "github.com/go-akka/configuration" ​ type Config struct { Port uint16 `yaml:"port"` Debug bool   `yaml:"debug"` Raw   *configuration.Config } ​ func (c *Config) parseConfig(path string) *Config { c.Raw = configuration.LoadConfig(path) c.Port = uint16(c.Raw.GetInt32("port", 8008)) c.Debug = c.Raw.GetBoolean("debug", false) return c }

测试config_test.go

func TestConfig(t *testing.T) { assert.NotPanics(t, func() { cfg := new(Config).parseConfig("./cfg.yaml") fmt.Printf(" port=%d,debug=%t", cfg.Port, cfg.Debug) }) }

三、godotenv实践

测试文件 .env

Key1=value1 Key2 =value2

解析配置config.go

func init() { if err := godotenv.Load("./.env"); err != nil { log.Fatal("Error loading .env file") } } ​ func ReadEnv() { value1 := os.Getenv("Key1") value2 := os.Getenv("Key2") value3 := os.Getenv("Key3") if value1 == "" || value2 == "" { panic("load error") } fmt.Printf("key1=%s,key2=%s,key3=%s", value1, value2, value3) } ​

测试文件config_test.go

func TestEnv(t *testing.T) { assert.NotPanics(t, func() { ReadEnv() }) }

四、gonfig 实践

配置文件

dev_config.json

{   "DB_USERNAME": "test",   "DB_PASSWORD": "test",   "DB_PORT": "3306",   "DB_HOST": "127.0.0.1",   "DB_NAME": "test" }

prd_config.json

{   "DB_USERNAME": "prd_test",   "DB_PASSWORD": "prd_test",   "DB_PORT": "3306",   "DB_HOST": "127.0.0.1",   "DB_NAME": "prd_test" }

配置解析config.go

type Configuration struct { DB_USERNAME string DB_PASSWORD string DB_PORT     string DB_HOST     string DB_NAME     string } ​ func ParseConfig(params ...string) Configuration { configuration := Configuration{} env := "dev" if len(params) > 0 { env = params[0] } fName := fmt.Sprintf("./%s_config.json", env) if err := gonfig.GetConf(fName, &configuration); err != nil { panic(err) } return configuration }

测试文件config_test.go

func TestConfig(t *testing.T) { assert.NotPanics(t, func() { fmt.Println("Dev Conf :") cfg := ParseConfig() fmt.Printf("userName=%s,password=%s,port=%s,host=%s,name=%s \n", cfg.DB_USERNAME, cfg.DB_PASSWORD, cfg.DB_PORT, cfg.DB_HOST, cfg.DB_NAME) cfg = ParseConfig("prd") fmt.Printf("userName=%s,password=%s,port=%s,host=%s,name=%s \n", cfg.DB_USERNAME, cfg.DB_PASSWORD, cfg.DB_PORT, cfg.DB_HOST, cfg.DB_NAME) }) ​ }

五、viper实践

配置文件config.yml

server: port: 8080 ​ database: dbname: dbuser: "dbuser" dbpassword: "dbpassword" ​ EXAMPLE_VAR: "variable from config.yml" EXAMPLE_PATH: "path from config.yml"

解析配置config.go

type Configurations struct { Server       ServerConfigurations Database     DatabaseConfigurations EXAMPLE_PATH string EXAMPLE_VAR string } ​ // ServerConfigurations exported type ServerConfigurations struct { Port int } ​ // DatabaseConfigurations exported type DatabaseConfigurations struct { DBName     string DBUser     string DBPassword string } ​ func readConfig() { viper.SetConfigName("config") viper.AddConfigPath(".") viper.AutomaticEnv() viper.SetConfigType("yml") var configuration Configurations if err := viper.ReadInConfig(); err != nil { fmt.Printf("Error reading config file, %s", err) } viper.SetDefault("database.dbname", "test_db") err := viper.Unmarshal(&configuration) if err != nil { fmt.Printf("Unable to decode into struct, %v", err) } fmt.Printf("reading using model:\n database=%s,port=%d,path=%s,var=%s \n", configuration.Database.DBName, configuration.Server.Port, configuration.EXAMPLE_PATH, configuration.EXAMPLE_VAR) fmt.Printf("reading without model:\n database=%s,port=%d,path=%s,var=%s \n", viper.GetString("database.dbname"), viper.GetInt("server.port"), viper.GetString("EXAMPLE_PATH"), viper.GetString("EXAMPLE_VAR")) }

测试文件config_test.go

func TestConfig(t *testing.T) { assert.NotPanics(t, func() { readConfig() }) }

六、总结

四种读取环境配置的实践按照各自情况挑选吧,生产环境建议还是使用vipergodotenv,毕竟千锤百炼要可靠很多,还有友情提示永远不要忘记在.gitignore 中包含你的环境变量文件

github repo


哥佬倌,莫慌到走!觉好留个赞,探讨上评论。欢迎关注实践go语言专栏gothing,手把手一起学习go。也欢迎关注我,一定做一个长更的好男人。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值