Go几种读取配置文件的方式


比较有名的方案有

使用viper管理配置[1]


  • 支持多种配置文件格式,包括 JSON,TOML,YAML,HECL,envfile,甚至还包括Java properties
  • 支持为配置项设置默认值
  • 可以通过命令行参数覆盖指定的配置项
  • 支持参数别名

viper[2]按照这个优先级(从高到低)获取配置项的取值:

  • explicit call to Set: 在代码逻辑中通过viper.Set()直接设置配置项的值
  • flag:命令行参数
  • env:环境变量
  • config:配置文件
  • key/value store:etcd或者consul
  • default:默认值

按照这个优先级(从高到低)获取配置项的取值:

  • explicit call to Set: 在代码逻辑中通过viper.Set()直接设置配置项的值
  • flag:命令行参数
  • env:环境变量
  • config:配置文件
  • key/value store:etcd或者consul
  • default:默认值

优先级


验证一下 viper.Set() 的优先级高于 配置文件


package main

import (
 "fmt"

 "github.com/spf13/viper"
)

func main() {

 loadConfig()
}

func loadConfig() {

 configVar := "shuang-config.yaml"
 configVar = "" // 这行如果注释掉,则从指定的configVar读取配置文件;否则就各种条件去找了

 viper.Set("Global.Source""优先级最高")

 if configVar != "" {
  // SetConfigFile 显式定义配置文件的路径、名称和扩展名。
  // Viper 将使用它而不检查任何配置路径。
  viper.SetConfigFile(configVar)
 } else {

  // 如果没有显式指定配置文件,则

  // 会去下面的路径里找文件名`cui-config`的文件  name of config file (without extension)
  // 按照 []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}的顺序(居然还支持Java用的properties)
  viper.SetConfigName("cui-config")
  viper.AddConfigPath("/etc/myapp"// 找寻的路径
  viper.AddConfigPath("$HOME/.myapp/")
  viper.AddConfigPath(".")
 }

 err := viper.ReadInConfig()
 if err != nil {
  panic(fmt.Errorf("error reading config: %s", err))
 }

 fmt.Printf("到底用的是哪个配置文件: '%s'\n", viper.ConfigFileUsed())

 fmt.Printf("Global.Source这个字段的值为: '%s'\n", viper.GetString("global.source"))
}

输出:

到底用的是哪个配置文件: '/Users/fliter/config-demo/cui-config.yaml'
Global.Source这个字段的值为: '优先级最高'




验证一下 环境变量 的优先级高于 配置文件


package main

import (
 "fmt"

 "github.com/spf13/viper"
)

func main() {

 loadConfig()
}

func loadConfig() {

 configVar := "shuang-config.yaml"
 configVar = "" // 这行如果注释掉,则从指定的configVar读取配置文件;否则就各种条件去找了

 viper.Set("Global.Source""优先级最高")
 viper.AutomaticEnv()

 if configVar != "" {
  // SetConfigFile 显式定义配置文件的路径、名称和扩展名。
  // Viper 将使用它而不检查任何配置路径。
  viper.SetConfigFile(configVar)
 } else {

  // 如果没有显式指定配置文件,则

  // 会去下面的路径里找文件名`cui-config`的文件  name of config file (without extension)
  // 按照 []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}的顺序(居然还支持Java用的properties)
  viper.SetConfigName("cui-config")
  viper.AddConfigPath("/etc/myapp"// 找寻的路径
  viper.AddConfigPath("$HOME/.myapp/")
  viper.AddConfigPath(".")
 }

 err := viper.ReadInConfig()
 if err != nil {
  panic(fmt.Errorf("error reading config: %s", err))
 }

 fmt.Printf("到底用的是哪个配置文件: '%s'\n", viper.ConfigFileUsed())

 fmt.Printf("LANG这个字段的值为: '%s'\n", viper.GetString("LANG"))
}
alt

viper.AutomaticEnv()会绑定所有环境变量,

如果只希望绑定特定的,可以使用SetEnvPrefix("global.source", "MYAPP_GLOAL_SOURCE"),注意这个函数不会自动加上MYAPP的前缀.




验证一下 命令行参数的优先级高于 配置文件


viper可以配合pflag来使用,pflag可以理解为标准库flag的一个增强版,viper可以绑定到pflag上

和cobra,viper一样,pflag也是同一作者的作品

alt



验证一下 默认值的优先级低于 配置文件


package main

import (
 "fmt"

 "github.com/spf13/viper"
)

func main() {

 loadConfig()
}

func loadConfig() {

 configVar := "shuang-config.yaml"
 configVar = "" // 这行如果注释掉,则从指定的configVar读取配置文件;否则就各种条件去找了

 //viper.Set("Global.Source", "优先级最高")
 viper.AutomaticEnv()

 viper.SetDefault("Global.Source""优先级最低")

 if configVar != "" {
  // SetConfigFile 显式定义配置文件的路径、名称和扩展名。
  // Viper 将使用它而不检查任何配置路径。
  viper.SetConfigFile(configVar)
 } else {

  // 如果没有显式指定配置文件,则

  // 会去下面的路径里找文件名`cui-config`的文件  name of config file (without extension)
  // 按照 []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}的顺序(居然还支持Java用的properties)
  viper.SetConfigName("cui-config")
  viper.AddConfigPath("/etc/myapp"// 找寻的路径
  viper.AddConfigPath("$HOME/.myapp/")
  viper.AddConfigPath(".")
 }

 err := viper.ReadInConfig()
 if err != nil {
  panic(fmt.Errorf("error reading config: %s", err))
 }

 fmt.Printf("到底用的是哪个配置文件: '%s'\n", viper.ConfigFileUsed())

 fmt.Printf("Global.Source这个字段的值为: '%s'\n", viper.GetString("Global.Source"))
}
alt



Watch机制(配置更新后 热加载)


该机制可以监听配置文件的修改, 这样就实现了热加载,修改配置后,无需重启服务

  • 对于本地文件,是通过fsnotify实现的,然后通过一个回调函数去通知应用来reload;

  • 对于Remote KV Store,目前只支持etcd,做法比较ugly,(5秒钟)轮询一次 而不是watch api

package main

import (
 "fmt"
 "time"

 "github.com/fsnotify/fsnotify"
 "github.com/spf13/viper"
)

func main() {

 loadConfig()
}

func loadConfig() {

 configVar := "shuang-config.yaml"
 configVar = "" // 这行如果注释掉,则从指定的configVar读取配置文件;否则就各种条件去找了

 if configVar != "" {
  // SetConfigFile 显式定义配置文件的路径、名称和扩展名。
  // Viper 将使用它而不检查任何配置路径。
  viper.SetConfigFile(configVar)
 } else {

  // 如果没有显式指定配置文件,则

  // 会去下面的路径里找文件名`cui-config`的文件  name of config file (without extension)
  // 按照 []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}的顺序(居然还支持Java用的properties)
  viper.SetConfigName("cui-config")
  viper.AddConfigPath("/etc/myapp"// 找寻的路径
  viper.AddConfigPath("$HOME/.myapp/")
  viper.AddConfigPath(".")
 }

 viper.WatchConfig()
 viper.OnConfigChange(func(e fsnotify.Event) {
  fmt.Printf("配置文件 %s 发生了更改!!! 最新的Global.Source这个字段的值为 %s:", e.Name, viper.GetString("Global.Source"))
 })

 err := viper.ReadInConfig()
 if err != nil {
  panic(fmt.Errorf("error reading config: %s", err))
 }

 fmt.Printf("到底用的是哪个配置文件: '%s'\n", viper.ConfigFileUsed())

 fmt.Printf("Global.Source这个字段的值为: '%s'\n", viper.GetString("Global.Source"))

 time.Sleep(10000e9)
}
alt

Go viper 配置文件读取工具[3]

动态获取配置文件(viper)[4]




configor[5]


Configor: 一个Golang配置工具,支持YAML,JSON,TOML,Shell环境,支持热加载

出自jinzhu大佬[6]

alt

package main

import (
 "fmt"

 "github.com/jinzhu/configor"
)

type Config struct {
 APPName string `default:"app name"`
 DB      struct {
  Name     string
  User     string `default:"root"`
  Password string `required:"true" env:"DBPassword"`
  Port     uint   `default:"3306"`
 }
 Contacts []struct {
  Name  string
  Email string `required:"true"`
 }
}

func main() {
 var conf = Config{}
 err := configor.Load(&conf, "config.yml")

 // err := configor.New(&configor.Config{Debug: true}).Load(&conf, "config.yml")  // 测试模式,也可以通过环境变量开启测试模式(CONFIGOR_DEBUG_MODE=true go run main.go ),这样就无需修改代码

 //err := configor.New(&configor.Config{Verbose: true}).Load(&conf, "config.yml") // 模式,也可以通过环境变量开启详细模式(CONFIGOR_VERBOSE_MODE=true go run main.go ),这样就无需修改代码
 if err != nil {
  panic(err)
 }
 fmt.Printf("%v \n", conf)
}

开启 测试模式 or 详细模式


既可以在代码中显式开启,如 err := configor.New(&configor.Config{Debug: true}).Load(&conf, "config.yml")

也可以通过环境变量开启,如 CONFIGOR_DEBUG_MODE=true go run main.go


加载多个配置文件


// application.yml 的优先级 大于 database.json, 排在前面的配置文件优先级大于排在后的的配置
configor.Load(&Config, "application.yml""database.json")

根据环境变量加载配置文件 or 从shell加载配置项


详细可参考 Golang Configor 配置文件工具[7]


热更新


package main

import (
 "fmt"
 "time"

 "github.com/jinzhu/configor"
)

type Config struct {
 APPName string `default:"app name"`
 DB      struct {
  Name     string
  User     string `default:"root"`
  Password string `required:"true" env:"DBPassword"`
  Port     uint   `default:"3306"`
 }
 Contacts []struct {
  Name  string
  Email string `required:"true"`
 }
}

func main() {
 var conf = Config{}

 // reload模式,可实现热加载

 err := configor.New(&configor.Config{
  AutoReload:         true,
  AutoReloadInterval: time.Second,
  AutoReloadCallback: func(config interface{}) {
   // config发生变化后出发什么操作
   fmt.Printf("配置文件发生了变更%#v\n", config)
  },
 }).Load(&conf, "config.yml")

 // 无reload模式
 //err := configor.Load(&conf, "config.yml")

 // err := configor.New(&configor.Config{Debug: true}).Load(&conf, "config.yml")  // 测试模式,也可以通过环境变量开启测试模式(CONFIGOR_DEBUG_MODE=true go run main.go ),这样就无需修改代码

 //err := configor.New(&configor.Config{Verbose: true}).Load(&conf, "config.yml") // 模式,也可以通过环境变量开启详细模式(CONFIGOR_VERBOSE_MODE=true go run main.go ),这样就无需修改代码
 if err != nil {
  panic(err)
 }
 fmt.Printf("%v \n", conf)

 time.Sleep(100000e9)
}
alt

完整代码[8]

参考资料

[1]

使用viper管理配置: https://cloud.tencent.com/developer/article/1540672

[2]

viper: https://github.com/spf13/viper

[3]

Go viper 配置文件读取工具: https://cloud.tencent.com/developer/article/1677426

[4]

动态获取配置文件(viper): https://segmentfault.com/a/1190000022828484

[5]

configor: https://github.com/jinzhu/configor

[6]

jinzhu大佬: https://github.com/jinzhu

[7]

Golang Configor 配置文件工具: https://www.jianshu.com/p/f826d2cc361b

[8]

完整代码: https://github.com/cuishuang/config-demo

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/100072.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

爬虫逆向实战(二十八)--某税网第一步登录

一、数据接口分析 主页地址:某税网 1、抓包 通过抓包可以发现登录接口是factorAccountLogin 2、判断是否有加密参数 请求参数是否加密? 通过查看载荷模块可以发现有一个datagram 和 一个signature加密参数 请求头是否加密? 通过查看“标…

11 mysql float/double/decimal 的数据存储

前言 这里主要是 由于之前的一个 datetime 存储的时间 导致的问题的衍生出来的探究 探究的主要内容为 int 类类型的存储, 浮点类类型的存储, char 类类型的存储, blob 类类型的存储, enum/json/set/bit 类类型的存储 本文主要 的相关内容是 float, decimal 类类型的相关数据…

电脑提示找不到concrt140.dll怎么修复?concrt140.dll快速修复方法

今天,我将和大家分享一个关于电脑计算机中丢失concrt140.dll文件的问题及其修复方法。希望通过这次演讲,能够帮助大家解决在日常使用电脑过程中遇到的问题,提高我们的工作效率。 首先,让我们来了解一下concrt140.dll是什么。concr…

爬虫--爬取自己想去的目的的车票信息

前言: 本篇文章主要作为一个爬虫项目的小练习,来给大家进行一下爬虫的大致分析过程以及来帮助大家在以后的爬虫编写中有一个更加清晰的认识。 一:环境配置 Python版本:3.7 IDE:PyCharm 所需库:requests&#xff0…

ShardingJDBC——基于JPA的读写分离实战

摘要 本博文主要介绍基于JPA的读写分离实战,帮助大家更好的学会使用读写分离。透明化读写分离所带来的影响,让使用方尽量像使用一个数据库一样使用主从数据库集群,是ShardingSphere读写分离模块的主要设计目标。 一、读写分离库的场景和设计…

CSRF与XSS结合利用

文章目录 修改cms网站后台管理员密码成功登录总结 修改cms网站后台管理员密码 CSRF和XSS结合的JS代码&#xff1a; <script> xmlhttp new XMLHttpRequest(); xmlhttp.open("post","http://10.4.7.130/cms/admin/user.action.php",false); xmlhttp…

【位运算】leetcode面试题:消失的两个数字

一.题目描述 消失的两个数字 二.思路分析 本题难度标签是困难&#xff0c;但实际上有了只出现一次的数字iii这道题的铺垫&#xff0c;本题的思路还是很容易想到的。 温馨提示&#xff1a;阅读本文前可以先查看我的【位运算】专栏的第一篇文章&#xff0c;其中包含位运算这类…

NFTScan | 08.21~08.27 NFT 市场热点汇总

欢迎来到由 NFT 基础设施 NFTScan 出品的 NFT 生态热点事件每周汇总。周期&#xff1a;2023.08.21~ 2023.08.27 NFT Hot News 01/ NFT 品牌体验平台 Recur 将于 11 月 16 日彻底关闭&#xff0c;此前曾获 5000 万美元融资 8 月 21 日&#xff0c;NFT 品牌体验平台 Recur 在 X…

微信小程序 - 2023年最新版手机号快捷登录详细教程

前言 最近开发公司手机快捷登录的功能&#xff0c;花费了不少时间&#xff0c;这里附上详细教程。 这里以海底捞小程序的图片为例&#xff0c;如有侵权请联系小编删除。 代码如下 <button open-type"getPhoneNumber" getphonenumber"getPhoneNumber"…

8.31作业

一、面试题 1、什么是多态、虚函数、纯虚函数 多态是一种行为的多种实现方式&#xff0c;通过虚函数和虚指针来实现。是子类对父类虚函数重写然后父类通过虚指针调用重写后的实现。虚指针在类的最前面会指向一个虚函数表。里面记录了虚函数包括子类重写的。虚函数就是在函数前…

Linux(CentOS7)下如何配置多个Tomcat容器?

一、在 liunx 系统安装 jdk 1、安装jdk&#xff08;yum install 安装&#xff09; 查看是否系统是否自带jdk并卸载 rpm -qa |grep java rpm -qa |grep jdk rpm -qa |grep gcj 其中&#xff0c;GCJ是GNU的Java编译器,可以把java程序编译成本地代码&#xff0c;编译成功后的可…

Mybatis 动态SQL – 使用if, where标签动态生成条件语句

前面几篇我们介绍了使用Mybatis进行数据的增删改查&#xff0c;并且也了解了如何在Mybatis中使用JDK的日志系统打印日志&#xff1b;本篇我们继续介绍如何使用Mybatis提供的if,where标签动态生成条件语句。 如果您对数据的增删改查和Mybatis集成JDK日志系统不太了解&#xff0…

九、MySQL(DQL基础查询)如何查询表中信息?

1、DQL基础用法&#xff1a; 2、实例&#xff1a; &#xff08;1&#xff09;初始化表格&#xff1a; # 创建表头 create table things(id int comment 编号,number int comment 学号,name char(5) comment 姓名,address char(6) comment 地址,phone number int comment 电话…

stable diffusion实践操作-VAE

本文专门开一节写图生图相关的内容&#xff0c;在看之前&#xff0c;可以同步关注&#xff1a; stable diffusion实践操作 VAE&#xff0c;全名Variational autoenconder&#xff0c;中文叫变分自编码器。作用是&#xff1a;滤镜微调 &#xff0c;名字中带有vae&#xff0c;后…

AI图像行为分析算法 opencv

AI图像行为分析算法通过pythonopencv深度学习框架对现场操作行为进行全程实时分析&#xff0c;AI图像行为分析算法通过人工智能视觉能够准确判断出现场人员的作业行为是否符合SOP流程规定&#xff0c;并对违规操作行为进行自动抓拍告警。OpenCV是一个基于Apache2.0许可&#xf…

ViT论文Pytorch代码解读

ViT论文代码实现 论文地址&#xff1a;https://arxiv.org/abs/2010.11929 Pytorch代码地址&#xff1a;https://github.com/lucidrains/vit-pytorch ViT结构图 调用代码 import torch from vit_pytorch import ViTdef test():v ViT(image_size 256, patch_size 32, num_cl…

Rust 学习笔记(持续更新中…)

一、 编译和运行是单独的两步 运行 Rust 程序之前必须先编译&#xff0c;命令为&#xff1a;rustc 源文件名 - rustc main.rs编译成功之后&#xff0c;会生成一个二进制文件 - 在 Windows 上还会生产一个 .pdb 文件 &#xff0c;里面包含调试信息Rust 是 ahead-of-time 编译的…

外贸爬虫系统

全球智能搜索 全球智能搜索 支持全球所有国家搜索引擎&#xff0c;及社交平台&#xff0c;精准定位优质的外贸客户&#xff0c;免翻墙 全球任意国家地区实时采集 搜索引擎全网邮箱电话采集 社交平台一键查看采集&#xff08;Facebook,Twitter,Linkedin等&#xff09; 职位…

Pytorch 的基本概念和使用场景介绍

文章目录 一、基本概念1. 张量&#xff08;Tensor&#xff09;2. 自动微分&#xff08;Autograd&#xff09;3. 计算图&#xff08;Computation Graph&#xff09;4. 动态计算图&#xff08;Dynamic Computation Graph&#xff09;5. 变量&#xff08;Variable&#xff09; 二、…

微软表示Visual Studio的IDE即日起开启“退休”倒计时

据了解&#xff0c;日前有消息透露称&#xff0c;适用于 Mac平台的Visual Studio集成开发环境(IDE)于8月31日启动“退休”进程。 而这意味着Visual Studio for Mac 17.6将继续支持12个月&#xff0c;一直到2024年8月31日。    微软表示后续不再为Visual Studio for Mac开发…