当前位置: 首页 > news >正文

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 多平台发布

相关文章:

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

比较有名的方案有 使用viper管理配置[1] 支持多种配置文件格式,包括 JSON,TOML,YAML,HECL,envfile,甚至还包括Java properties 支持为配置项设置默认值 可以通过命令行参数覆盖指定的配置项 支持参数别名 viper[2]按照这个优先级(从高到低&am…...

每日一题(反转链表)

每日一题(反转链表) 206. 反转链表 - 力扣(LeetCode) 思路: 可以定义一个新的newhead结构体指针。再定义cur指针和next指针互相配合,将原链表中的节点从头到尾依次头插到newhead链表中,同时更…...

某人事系统架构搭建设计记录

首发博客地址 https://blog.zysicyj.top/ 先大致列一下基础情况 架构必须是微服务 场景上涉及大量查询操作,分析操作 存在临时大量写入的场景 并发并不高 对高可用要求较高,不能挂掉 对安全要求高 要能过等保测试等三方测试 使用人数并不多,十…...

uniapp 实现切换tab锚点定位到指定位置

1.主要使用uniapp scroll-view 组件的scroll-into-view属性实现功能 2.代码如下 <scroll-view:scroll-into-view"intoView"><u-tabsclass"tabs-list"change"tabChange":list"tabList"></u-tabs><view id"1&…...

华纳云:ssh登录22号端口拒绝连接Ubuntu?

如果您在尝试使用SSH登录Ubuntu服务器的时候遇到了22号端口拒绝连接的问题&#xff0c;您可以尝试以下几个步骤来解决问题&#xff1a; 确认SSH服务已启动&#xff1a; 确保Ubuntu服务器上的SSH服务已经正确启动。您可以在服务器上运行以下命令来检查SSH服务的状态&#xff1a…...

python conda实践 sanic框架gitee webhook实践

import subprocess import hmac import hashlib import base64 from sanic.response import text from sanic import Blueprint from git import Repo# 路由蓝图 hook_blue Blueprint(hook_blue)hook_blue.route(/hook/kaifa, methods["POST"]) async def kaifa(req…...

LeetCode——无重复的最长子串(中等)

题目 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度 示例 1: 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长度为 3。示例 2: 输入: s "bbbbb" 输出: 1 解释: 因为…...

【SQL】关系模型与查询和更新数据

一、关系模型 1.1 主键 主键是关系表中记录的唯一标识。主键的选取非常重要&#xff1a;主键不要带有业务含义&#xff0c;而应该使用BIGINT自增或者GUID类型。主键也不应该允许NULL。 可以使用多个列作为联合主键&#xff0c;但联合主键并不常用。 1.2 外键 FOREIGN KEY …...

【Centos8_配置单节点伪分布式Spark环境】

安装centos8 jdk部署伪分布式spark环境 安装Centos8 环境下的JDK 下载jdk linux版本 下载链接&#xff1a; jdk-8u381-linux-x64.tar.gz 将该文件上传到Centos8 主机 部署配置jdk&#xff08;java8&#xff09; # 解压到指定路径 [lhangtigerkeen Downloads]$ sudo tar …...

【软考】系统集成项目管理工程师(三)信息系统集成专业技术知识①【16分】

一、系统集成的特点 官方解释&#xff1a; 1、信息系统建设的内容主要包括设备采购、系统集成、软件开发和运维服务等&#xff1b; 2、信息系统集成是指将计算机软件、硬件、网络通信、信息安全等技术和产品集成为能够满足用户特定需求的信息系统&#xff1b;显著特点如下&am…...

揭秘特权账号潜在风险,你中招了吗?

什么是特权账号&#xff1f; 特权账号指在企业运营过程中&#xff0c;为相关业务运营、系统管理、系统运维等人员赋予的系统维护、权限增加、数据修改删除、导出等高级权限的系统账号。这些账号多数连接企业核心资源&#xff0c;保障企业内部各项业务正常运作。然而&#xff0…...

线性代数的学习和整理13: 定义域,值域,到达域 和单射,满射,双射,反函数,逆矩阵

目录 1 函数与 向量/矩阵 2 初等数学的函数 2.1 函数 2.2 函数的定义&#xff1a;定义域 →映射→ 值域 3 高等数学里的函数&#xff1a;定义域和陪域/到达域&#xff08;非值域&#xff09;的映射关系 3.1 函数 3.2 单射&#xff0c;满射&#xff0c;双射等都是针对…...

深入MaxCompute -第十一弹 -QUALIFY

简介&#xff1a; MaxCompute支持QUALIFY语法过滤Window函数的结果&#xff0c;使得查询语句更简洁易理解。Window函数和QUALIFY语法之间的关系可以类比聚合函数GROUP BY语法和HAVING语法。 MaxCompute&#xff08;原ODPS&#xff09;是阿里云自主研发的具有业界领先水平的分…...

Mysql定时备份事件

创建了一个名为backup_database的定时任务&#xff0c;每天自动在当前时间的后一天开始执行。备份数据库的代码使用mysqldump命令将数据库导出为sql文件保存在指定的备份目录中。 需要注意的是&#xff0c;上述代码中的用户名 (username)、密码 (password)、主机名 (hostname) …...

探索ClickHouse——安装和测试

我们在Ubuntu 20 Server版虚拟机上对ClickHouse进行探索。 安装 检测环境 grep -q sse4_2 /proc/cpuinfo && echo "SSE 4.2 supported" || echo "SSE 4.2 not supported"SSE 4.2 supported 可以看到我们的环境支持编译版本的。如果不支持的环境…...

常用的css样式

1&#xff1a;flex布局 .flex-between {display: flex;justify-content: space-between; }.flex-evenly {display: flex;justify-content: space-evenly; }.flex-end {display: flex;justify-content: flex-end; }.flex {display: flex; }.flex-center {display: flex;justify…...

小兔鲜儿 - 微信登录

目录 微信登录​ 登录方式 静态结构​ 获取登录凭证​ 获取手机号码​ 微信登录接口(生产环境) 模拟手机登录(开发环境) 用户信息持久化存储​ 涉及知识点&#xff1a;微信授权登录&#xff0c;文件上传&#xff0c;Store 状态管理等。 微信登录​ 微信小程序的开放…...

C++ Primer阅读笔记--对象移动(右值引用、移动迭代器和引用限定符的使用)

目录 1--右值引用 2--std::move 3--移动构造函数 4--移动赋值运算符 5--移动迭代器 6--引用限定符 1--右值引用 右值引用必须绑定到右值的引用&#xff0c;通过 && 获得右值引用&#xff1b; 右值引用只能绑定到临时对象&#xff08;即将被销毁的对象&#xff09…...

【办公类-16-01-02】2023年度上学期“机动班下午代班的排班表——跳过周三、节日和周末”(python 排班表系列)

背景需求&#xff1a; 2023年第一学期&#xff08;2023年9-2024年1月&#xff09;&#xff0c;我又被安排为“机动班”&#xff0c;根据新学期的校历&#xff0c;手动推算本学期的机动班的带班表 排版原则 1、班级数量&#xff1a;共有6个班级&#xff0c;循环滚动 2、每周次…...

ChatGPT HTML JS Echarts实现热力图展示

热力图是一种常用的数据可视化图表,主要用于展示数据的分布和密度情况。它通过使用不同颜色的热点来表示数据在地理或二维空间上的分布情况,从而直观地显示出数据的密集程度和趋势。 热力图的功能和作用如下: 1. 数据分布展示:热力图可以将大量数据以热点的形式展示在地理…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...