【Viper】配置格式与支持的数据源与go案例

Viper 是一个用于 Go 应用程序的配置管理库,支持多种配置格式和数据源。


安装依赖

go get github.com/spf13/viper
go get github.com/spf13/viper/remote
go get go.etcd.io/etcd/client/v3

"github.com/spf13/viper/remote"要写在etcd客户端import里

1. 配置格式—就是可以读的配置类型

Viper 支持多种常见的配置格式,包括:

  • JSON: 一种轻量级的数据交换格式,易于阅读和编写。
  • YAML: 一种人类可读的数据序列化格式,常用于配置文件。
  • TOML: 一种易于阅读的配置文件格式,旨在成为最小的配置文件格式。
  • HCL: HashiCorp 配置语言,用于描述基础设施配置。
  • Java Properties: 一种简单的键值对格式,常用于 Java 应用程序。
  • INI: 一种简单的配置文件格式,常用于 Windows 应用程序。
  • Envfile: 环境变量文件格式,通常用于存储环境变量。

2. 支持的数据源—可以从哪里导入要读的配置

Viper 不仅支持从文件中读取配置,还支持从多种数据源获取配置,包括:

  • 文件: 从本地文件系统中读取配置文件。
  • 环境变量: 从操作系统的环境变量中读取配置。
  • io.Reader: 从Reader中读取配置。
  • 远程配置系统: 从远程配置系统(如 etcd、Consul)中读取配置。

Viper 支持的四种常见数据源的简单实现:

1. 文件

Viper 支持从多种文件格式中读取配置,包括 JSON、YAML、TOML、HCL、INI 等。

使用方法

  • 设置配置文件路径和名称
    viper.SetConfigName("config") // 配置文件名称(不带扩展名)
    viper.SetConfigType("yaml")   // 配置文件类型(如 yaml、json 等)
    viper.AddConfigPath(".")      // 配置文件搜索路径
    
  • 读取配置文件
    if err := viper.ReadInConfig(); err != nil {log.Fatalf("Error reading config file: %s", err)
    }
    

示例

假设有一个 config.yaml 文件:

database:host: localhostport: 5432

读取配置:

viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
if err := viper.ReadInConfig(); err != nil {log.Fatal(err)
}
fmt.Println("Database Host:", viper.GetString("database.host"))
fmt.Println("Database Port:", viper.GetInt("database.port"))

2. 环境变量

Viper 可以从操作系统的环境变量中读取配置,适合在容器化或云原生环境中使用。

使用方法

  • 启用环境变量支持
    viper.AutomaticEnv() // 自动绑定环境变量
    
  • 设置环境变量前缀(可选):
    viper.SetEnvPrefix("MYAPP") // 环境变量前缀(如 MYAPP_DATABASE_HOST)
    
  • 绑定特定键到环境变量
    viper.BindEnv("database.host", "DB_HOST") // 将 database.host 绑定到环境变量 DB_HOST
    

示例

假设设置了环境变量:

export DB_HOST=localhost
export DB_PORT=5432

读取配置:

viper.AutomaticEnv()
viper.BindEnv("database.host", "DB_HOST")
viper.BindEnv("database.port", "DB_PORT")
fmt.Println("Database Host:", viper.GetString("database.host"))
fmt.Println("Database Port:", viper.GetInt("database.port"))

3. io.Reader

Viper 支持从实现了 io.Reader 接口的对象中读取配置,适合从内存或网络流中加载配置。

使用方法

  • io.Reader 读取配置
    configData := []byte(`{"database": {"host": "localhost", "port": 5432}}`)
    reader := bytes.NewReader(configData)
    viper.SetConfigType("json") // 设置配置类型
    if err := viper.ReadConfig(reader); err != nil {log.Fatal(err)
    }
    

示例

configData := []byte(`
database:host: localhostport: 5432
`)
reader := bytes.NewReader(configData)
viper.SetConfigType("yaml")
if err := viper.ReadConfig(reader); err != nil {log.Fatal(err)
}
fmt.Println("Database Host:", viper.GetString("database.host"))
fmt.Println("Database Port:", viper.GetInt("database.port"))

4. etcd

Viper 支持从 etcd(分布式键值存储)中读取配置,适合分布式系统的配置管理。

使用方法

  • 安装 etcd 支持
    go get github.com/spf13/viper/remote
    
  • 配置 etcd 客户端
    import ("github.com/spf13/viper"_ "github.com/spf13/viper/remote"
    )
    
  • 从 etcd 读取配置
    viper.AddRemoteProvider("etcd", "http://127.0.0.1:2379", "/config/path")
    viper.SetConfigType("yaml") // 设置配置类型
    if err := viper.ReadRemoteConfig(); err != nil {log.Fatal(err)
    }
    

示例

假设 etcd 中存储了以下配置:

database:host: localhostport: 5432

读取配置:

viper.AddRemoteProvider("etcd", "http://127.0.0.1:2379", "/config/path")
viper.SetConfigType("yaml")
if err := viper.ReadRemoteConfig(); err != nil {log.Fatal(err)
}
fmt.Println("Database Host:", viper.GetString("database.host"))
fmt.Println("Database Port:", viper.GetInt("database.port"))

总结

  • 文件:适合本地开发和静态配置。
  • 环境变量:适合容器化或云原生环境。
  • io.Reader:适合从内存或网络流中加载配置。
  • etcd:适合分布式系统的动态配置管理。

综合go案例

config.env

env=dev
server.ip=127.0.0.1
server.port=8080
courses=["golang", "C/C++", "音视频", "kernel", "dpdk", "面试题", "游戏"]

config.json

{"env": "dev","server": {"ip":"127.0.0.1","port": 8085},"courses": ["golang","C/C++","音视频","kernel","dpdk","面试题","游戏"],"list": [{"name": "golang","author": "nick"},{"name": "C/C++","author": "king"},{"name": "kernel","author": "vico"},{"name": "音视频","author": "Darren"},{"name": "游戏","author": "mark"}]
}

config.noext

# 键值
env: dev
# 对象或map
server:ip: 127.0.0.1port: 8080
# 数组或列表
courses:- "golang"- "C/C++"- "音视频"- "kernel"- "dpdk"- "面试题"- "游戏"list:- name: golangauthor: nick- name: C/C++author: king- name: kernelauthor: vico- name: 音视频author: Darren- name: 游戏author: mark

config.yaml

# 键值
env: dev
# 对象或map
server:ip: 127.0.0.1port: 8080
# 数组或列表
courses:- "golang"- "C/C++"- "音视频"- "kernel"- "dpdk"- "面试题"- "游戏"list:- name: golangauthor: nick- name: C/C++author: king- name: kernelauthor: vico- name: 音视频author: Darren- name: 游戏author: mark

data_source.go

package configimport ("github.com/spf13/viper"_ "github.com/spf13/viper/remote""io""log"
)// LoadFromFile 加载配置文件。
// 该函数使用 vipers 去从指定的文件路径加载配置。
// 参数:
//
//	filepath - 配置文件的路径。
//	typ - 可选参数,指定配置文件的类型。
//
// 返回值:
//
//	*viper.Viper - 加载了配置文件数据的 viper 实例。
//	error - 如果加载配置文件时发生错误,返回该错误。
func LoadFromFile(filepath string, typ ...string) (*viper.Viper, error) {// 创建一个新的 viper 实例。v := viper.New()// 设置配置文件的路径。v.SetConfigFile(filepath)// 如果提供了配置文件类型,则设置配置文件类型。if len(typ) > 0 {v.SetConfigType(typ[0])}// 读取并解析配置文件到viper中。err := v.ReadInConfig()// 返回 viper 实例和可能的错误。return v, err
}// LoadFromEnv 初始化一个viper实例,并将其配置为自动从环境变量中加载配置。
// 该函数返回一个指向viper实例的指针,以及一个错误(此示例中未实现错误处理)。
func LoadFromEnv() (*viper.Viper, error) {// 创建一个新的viper实例。v := viper.New()// 启用自动环境变量加载,viper将自动查找与结构体字段同名的环境变量。//v.AutomaticEnv()// 手动绑定环境变量GOPATH和GOROOT到viper实例。// 这样做是为了方便地从环境变量中读取这些值,而无需手动查询环境变量。v.BindEnv("GOPATH")v.BindEnv("GOROOT")// 返回viper实例指针,以及nil作为错误值,表示没有发生错误。return v, nil
}// LoadFromIoReader 从 io.Reader 类型的参数中加载配置信息。
// 此函数主要用于从不同的读取源(如文件、网络流等)中加载配置,
// 并根据提供的 typ 参数设置配置的类型。
// 参数:
//   - reader: io.Reader 类型的接口,代表任何可以读取字节流的对象。
//   - typ: 字符串,指定配置文件的类型(例如 "json"、"yaml")。
//
// 返回值:
//   - *viper.Viper: 一个指向 viper.Viper 实例的指针,用于进一步操作或获取配置信息。
//   - error: 在读取配置过程中遇到的错误(如果有)。
func LoadFromIoReader(reader io.Reader, typ string) (*viper.Viper, error) {// 创建一个新的 viper 实例。v := viper.New()// 设置配置类型,根据传入的 typ 参数。v.SetConfigType(typ)// 从 reader 参数指定的源中读取配置信息。err := v.ReadConfig(reader)// 返回 viper 实例和可能的错误。return v, err
}// LoadFromEtcd loadFromEtcd 从 Etcd 中加载配置信息。
// 参数:
//
//	etcdAddr: Etcd服务器的地址。
//	key: 配置在Etcd中的键路径。
//	typ: 配置文件的类型。
//
// 返回值:
//
//	*viper.Viper: 加载配置后的Viper实例指针。
//	error: 错误信息,如果有的话。
func LoadFromEtcd(etcdAddr, key, typ string) (*viper.Viper, error) {// 创建一个新的Viper实例。v := viper.New()// 为Viper实例添加Etcd3远程提供者。// 这里可能会出现错误,如果提供的Etcd地址或键路径无效。err := v.AddRemoteProvider("etcd3", etcdAddr, key)if err != nil {// 记录错误信息。log.Println(err)// 返回nil和错误信息。return nil, err}// 设置Viper实例的配置类型。v.SetConfigType(typ)// 从远程提供者读取配置信息。// 这里可能会出现错误,如果无法从远程提供者获取配置信息。err = v.ReadRemoteConfig()// 返回Viper实例和可能的错误信息。return v, err
}

main.go

package mainimport ("bytes""context""fmt"clientv3 "go.etcd.io/etcd/client/v3""golang20-viper/config""log""os"
)func main() {//loadFile()//loadEnv()//loadReader()loadEtcd()
}// loadFile 函数演示了如何从不同格式的配置文件中加载配置。
// 它依次尝试加载 .env, .json, .yaml, .toml 和 .yaml 文件,并打印出特定配置项的值。
func loadFile() {// 从 "config.env" 文件加载配置,并打印出环境、服务器端口和课程信息。v1, err := config.LoadFromFile("config.env", "env")fmt.Println("config.env", err, v1.Get("env"), v1.Get("server.port"), v1.Get("courses"))// 从 "config.json" 文件加载配置,包括环境、服务器端口、课程信息和作者信息。v2, err := config.LoadFromFile("config.json")fmt.Println("config.json", err, v2.Get("env"), v2.Get("server.port"), v2.Get("courses").([]any)[0], v2.Get("list").([]any)[0].(map[string]any)["author"])// 从 "config.noext" 文件加载 YAML 格式的配置,同样打印环境、服务器端口、课程信息和作者信息。v3, err := config.LoadFromFile("config.noext", "yaml")fmt.Println("config.noext", err, v3.Get("env"), v3.Get("server.port"), v3.Get("courses").([]any)[0], v3.Get("list").([]any)[0].(map[string]any)["author"])// 从 "config.toml" 文件加载配置,展示如何获取嵌套配置项的值。v4, err := config.LoadFromFile("config.toml")fmt.Println("config.toml", err, v4.Get("env"), v4.Get("server.port"), v4.Get("courses").(map[string]any)["list"].([]any)[0], v4.Get("list").([]any)[0].(map[string]any)["author"])// 从 "config.yaml" 文件加载配置,再次打印出环境、服务器端口、课程信息和作者信息,验证不同格式文件的兼容性。v5, err := config.LoadFromFile("config.yaml")fmt.Println("config.yaml", err, v5.Get("env"), v5.Get("server.port"), v5.Get("courses").([]any)[0], v5.Get("list").([]any)[0].(map[string]any)["author"])
}func loadEnv() {v, err := config.LoadFromEnv()fmt.Println(err, v.Get("GOROOT"), v.Get("gopath"))
}// loadReader 读取配置文件并解析特定配置项。
// 该函数没有输入参数和返回值。
// 功能描述:
// 1. 读取名为 "config.yaml" 的配置文件。
// 2. 如果读取过程中遇到错误,记录错误信息并终止程序运行。
// 3. 使用 bytes.NewReader 创建一个字节流读取器来读取配置文件内容。
// 4. 调用 config.LoadFromIoReader 函数从字节流读取器中加载配置信息。
// 5. 打印解析后的配置项,包括环境变量、服务器端口、课程信息和作者信息。
func loadReader() {// 读取配置文件 "config.yaml" 的内容到 byteList。byteList, err := os.ReadFile("config.yaml")if err != nil {// 如果读取配置文件时发生错误,记录错误信息并终止程序。log.Fatalln(err)}// 创建一个新的字节流读取器来读取配置文件内容。r := bytes.NewReader(byteList)// 从字节流读取器中加载配置信息,并处理可能的错误。v, err := config.LoadFromIoReader(r, "yaml")// 打印解析后的配置项。fmt.Println("io.reader", err, v.Get("env"), v.Get("server.port"), v.Get("courses").([]any)[0], v.Get("list").([]any)[0].(map[string]any)["author"])
}// loadEtcd 函数用于从本地文件加载配置并写入到 etcd 中,然后从 etcd 中读取配置并打印部分配置项。
// 该函数不接收任何参数,也不返回任何值。
func loadEtcd() {// 定义 etcd 的地址、配置项的键以及本地配置文件的路径etcdAddr := "192.168.88.131:2379"key := "/0voice/viper/config.yaml"loaclFilepath := "config.yaml"// 将本地配置文件的内容写入到 etcd 中writeConfToEtcd(etcdAddr, key, loaclFilepath)// 从 etcd 中加载配置,并解析为 yaml 格式v, err := config.LoadFromEtcd(etcdAddr, key, "yaml")// 打印从 etcd 中读取的配置项,包括环境、服务器端口、课程列表中的第一个课程以及列表中的第一个作者的名称fmt.Println("etcd", err, v.Get("env"), v.Get("server.port"), v.Get("courses").([]any)[0], v.Get("list").([]any)[0].(map[string]any)["author"])//fmt.Println(err, v)
}// writeConfToEtcd 将本地配置文件内容写入到etcd指定键中
// 参数说明:
//   - etcdAddr: etcd服务地址,格式为"IP:PORT"
//   - key: etcd中存储配置的键名
//   - localFilepath: 本地配置文件的路径
//
// 功能说明:
//
//	读取配置文件,将其内容存入etcd集群的指定键中
//	遇到任何错误(文件读取、连接etcd、写入etcd)将直接终止程序
func writeConfToEtcd(etcdAddr, key, localFilepath string) {// 从固定路径读取配置文件内容byteList, err := os.ReadFile(localFilepath)if err != nil {// 如果读取配置文件时发生错误,记录错误信息并终止程序。log.Fatalln(err)}v := string(byteList)// 创建etcd客户端连接cli, err := clientv3.New(clientv3.Config{Endpoints: []string{etcdAddr},})if err != nil {log.Fatal(err)}// 将配置内容写入etcd指定键_, err = cli.Put(context.Background(), key, v)if err != nil {log.Fatal(err)}
}

etcd docker部署

docker run -d \
-p 2379:2379 \
-p 2380:2380 \
--restart always \
--volume=/home/etcd:/etcd-data \
--name etcd quay.io/coreos/etcd:v3.5.7 \
/usr/local/bin/etcd \
--data-dir=/etcd-data --name node1 \
--initial-advertise-peer-urls http://192.168.239.161:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--advertise-client-urls http://192.168.239.161:2379 \
--listen-client-urls http://0.0.0.0:2379 \
--initial-cluster node1=http://192.168.239.161:2380 \
--initial-cluster-token tkn \
--initial-cluster-state new

https://github.com/0voice

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C/C++】后缀表达式 蓝桥杯/ACM备赛

核心考点:1.栈的应用 2.字符串处理 题目描述 所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的…

【AI实践】deepseek支持升级git

当前Windows 11 WSL的git是2.17,Android Studio提示需要升级到2.19版本 网上找到指导文章 安装git 2.19.2 cd /usr/src wget https://www.kernel.org/pub/software/scm/git/git-2.19.2.tar.gz tar xzf git-2.19.2.tar.gz cd git-2.19.2 make prefix/usr/l…

QEMU 搭建 Ubuntu x86 虚拟机

1. 安装 QEMU 在 Ubuntu 系统中,可以通过以下命令安装 QEMU: sudo apt-get update sudo apt-get install qemu-system-x86_64 qemu-kvm libvirt-daemon libvirt-clients bridge-utils virt-manager2. 创建虚拟硬盘镜像 qemu-img create -f raw ubuntu…

Linux驱动层学习:Linux 设备树

设备树是一种数据结构,包含多个节点,用于描述硬件设备及其配置信息,它通常用于嵌入式系统中,尤其是在Linux操作系统中,帮助操作系统识别和管理硬件资源,设备树不是代码,而是一种用数据描述硬件信…

金蝶云星空与钉钉高效数据集成案例分享

金蝶云星空数据集成到钉钉的技术案例分享 在企业信息化系统中,数据的高效流动和实时反馈是提升业务效率的关键。本文将聚焦于一个具体的系统对接集成案例:如何将金蝶云星空的数据集成到钉钉,并实现审核状态的回传提示。 本次集成方案名为“…

图形渲染(一)——Skia、OpenGL、Mesa 和 Vulkan简介

1.Skia —— 2D 图形库 Skia 是一个 2D 图形库,它的作用是为开发者提供一个高层次的绘图接口,方便他们进行 2D 图形渲染(比如绘制文本、形状、图像等)。Skia 本身不直接管理 GPU 或进行底层的渲染工作,而是通过 底层图…

GIT提错分支,回滚提交

1. 准备示例 假设我们有三次提交: test1:需要在 master 分支提交test2、test3:需要在 develop 分支提交 远端线上记录 2. 步骤 选择需要回退的记录: 选中需要回退的 commit,选择 Reset Current Branch to Here...。…

【原创】在ubuntu中搭建gradle开发环境

检查Linux版本 rootwww:~# hostnamectlStatic hostname: www.0x88.comIcon name: computer-vmChassis: vmMachine ID: 30fa955a36be492ca459599ef20bc508Boot ID: 37084dbe36f44adaa075e8f9a98f132eVirtualization: kvm Operating System: Ubuntu 22.04.5 LTSKernel: Linux 5.…

【JavaEE进阶】MyBatis入门

目录 🌴前言 🌲什么是MyBatis? 🌳准备工作 🚩创建工程 🚩配置数据库连接字符串 🚩数据准备 🚩编写持久层代码 🍃单元测试 🌴前言 在应⽤分层学习时,我们了解到…

以太网详解(八)传输层协议:TCP/UDP 协议

文章目录 传输层协议概述为什么需要传输层?传输层功能网络层与传输层在实现 “端到端” 传输的异同两类服务:面向连接/无连接服务 传输控制协议 TCPTCP 协议数据单元格式TCP 的重传机制快重传和快恢复快重传举例快恢复算法 用户数据报协议 UDPUDP 概述UDP 基本工作过…

Electron 客户端心跳定时任务调度库调研文档 - Node.js 任务调度库技术调研文档

Electron 客户端心跳定时任务调度库调研文档 - Node.js 任务调度库技术调研文档 本文将对七个流行的定时任务调度库:node-cron、rxjs、bull、node-schedule、agenda、bree、cron。这些库都可以用来处理定时任务,但它们的特点和适用场景有所不同。我们将从…

DeepSeek 开放平台无法充值 改用其他平台API调用DeepSeek-chat模型方法

近几天DeepSeek开放平台无法充值目前已经关闭状态,大家都是忙着接入DeepSeek模型 ,很多人想使用DeepSeek怎么办? 当然还有改用其他平台API调用方法,本文以本站的提供chatgpt系统为例,如何修改DeepSeek-chat模型API接口…

pix2text 使用经验

给同行打鸡血 😊 构建结构化的数理领域知识库: 提高可访问性和可搜索性 Markdown和LaTeX格式:这两种格式易于在线发布和共享,有助于提高数学内容的可访问性。搜索引擎优化:将PDF内容转换为标记语言,可以…

Linux(centos)系统安装部署MySQL8.0数据库(GLIBC版本)

安装前检查服务器glibc版本,下载对应版本包 rpm -qa | grep glibc mysql安装包及依赖包已整理好,下载地址:https://pan.quark.cn/s/3137acc814c0,下载即可安装 一、下载MySQL mysql安装包及依赖包已整理好,下载地址…

6.2.图的存储结构-邻接矩阵法

一.邻接矩阵法存储不带权图: 结点不带权值: 1.左图的无向图中,A到B直达的有一条路,所以A行B列的值为1; 左图的无向图中,A到F没有直达的路,所以A行F列的值为0; 结论:无…

【VB语言】EXCEL中VB宏的应用

【VB语言】EXCEL中VB宏的应用 文章目录 [TOC](文章目录) 前言一、EXCEL-VB1.实验过程2.代码 二、EXCEL-VB 生成.c.h文件1.实验过程2.代码 四、参考资料总结 前言 1.WPS-VB扩展包 提示:以下是本篇文章正文内容,下面案例可供参考 一、EXCEL-VB 1.实验过…

用deepseek学大模型05逻辑回归

deepseek.com:逻辑回归的目标函数,损失函数,梯度下降 标量和矩阵形式的数学推导,pytorch真实能跑的代码案例以及模型,数据,预测结果的可视化展示, 模型应用场景和优缺点,及如何改进解决及改进方法数据推导。…

2025年02月17日Github流行趋势

项目名称:OmniParser 项目地址url:https://github.com/microsoft/OmniParser 项目语言:Jupyter Notebook 历史star数:8971 今日star数:969 项目维护者:yadong-lu, ThomasDh-C, aliencaocao, nmstoker, kris…

RocketMQ 5.0安装部署

0.前言 在微服务架构逐渐成为主流的今天,消息队列如同数字世界的快递员,承担着系统间高效通信的重要使命。 Apache RocketMQ 自诞生以来,因其架构简单、业务功能丰富、具备极强可扩展性等特点被众多企业开发者以及云厂商广泛采用。历经十余…

Ubuntu 22.04.5 LTS 安装企业微信,(2025-02-17安装可行)

一、依赖包(Ubuntu 20.04/Debian 11) 点击下载https://www.spark-app.store/download_dependencies_latest 1、 下载最新的依赖包。 请访问星火应用商店依赖包下载页面, 下载最新的依赖包。2、解压依赖包 </