首页 > 其他分享 >Go 语言之 Viper 的使用

Go 语言之 Viper 的使用

时间:2023-06-18 15:33:09浏览次数:42  
标签:语言 err string 配置文件 viper Go config Viper

Go 语言之 Viper 的使用

Viper 介绍

Viperhttps://github.com/spf13/viper

安装

go get github.com/spf13/viper

Viper 是什么?

Viper 是一个针对 Go 应用程序的完整配置解决方案,包括12-Factor 应用程序。它可以在应用程序中工作,并且可以处理所有类型的配置需求和格式。它支持:

Viper is a complete configuration solution for Go applications including 12-Factor apps. It is designed to work within an application, and can handle all types of configuration needs and formats. It supports:

  • setting defaults
  • reading from JSON, TOML, YAML, HCL, envfile and Java properties config files
  • live watching and re-reading of config files (optional)
  • reading from environment variables
  • reading from remote config systems (etcd or Consul), and watching changes
  • reading from command line flags
  • reading from buffer
  • setting explicit values

Viper can be thought of as a registry for all of your applications configuration needs.

Viper 可以被认为是满足所有应用程序配置需求的注册表。

为什么使用 Viper?

在构建现代应用程序时,您不需要担心配置文件格式; 您需要专注于构建令人满意的软件。Viper 就是为此而生的。

Viper 可以为你做以下事情:

  1. Find, load, and unmarshal a configuration file in JSON, TOML, YAML, HCL, INI, envfile or Java properties formats.
  2. Provide a mechanism to set default values for your different configuration options.
  3. Provide a mechanism to set override values for options specified through command line flags.
  4. Provide an alias system to easily rename parameters without breaking existing code.
  5. Make it easy to tell the difference between when a user has provided a command line or config file which is the same as the default.

Viper uses the following precedence order. Each item takes precedence over the item below it:

  • explicit call to Set
  • flag
  • env
  • config
  • key/value store
  • default

Important: Viper configuration keys are case insensitive. There are ongoing discussions about making that optional.

重要提示: Viper 配置键是不区分大小写的。目前正在讨论是否将其设置为可选的。

Viper 实操 Putting Values into Viper

建立默认值

一个好的配置系统将支持默认值。密钥不需要默认值,但如果没有通过配置文件、环境变量、远程配置或标志设置密钥,则默认值非常有用。

Examples:

viper.SetDefault("ContentDir", "content")
viper.SetDefault("LayoutDir", "layouts")
viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})

读取配置文件

Viper 需要最小的配置,这样它就知道在哪里查找配置文件。Viper 支持 JSON、 TOML、 YAML、 HCL、 INI、 envfile 和 JavaProperties 文件。Viper 可以搜索多个路径,但目前单个 Viper 实例只支持单个配置文件。Viper 不默认任何配置搜索路径,将默认决策留给应用程序。

下面是如何使用 Viper 搜索和读取配置文件的示例。不需要任何特定的路径,但至少应该在需要配置文件的地方提供一个路径。

viper.SetConfigName("config") // name of config file (without extension)
viper.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name
viper.AddConfigPath("/etc/appname/")   // path to look for the config file in
viper.AddConfigPath("$HOME/.appname")  // call multiple times to add many search paths
viper.AddConfigPath(".")               // optionally look for config in the working directory
err := viper.ReadInConfig() // Find and read the config file
if err != nil { // Handle errors reading the config file
	panic(fmt.Errorf("fatal error config file: %w", err))
}

您可以处理没有如下配置文件的特定情况:

if err := viper.ReadInConfig(); err != nil {
	if _, ok := err.(viper.ConfigFileNotFoundError); ok {
		// Config file not found; ignore error if desired
	} else {
		// Config file was found but another error was produced
	}
}

// Config file found and successfully parsed

写入配置文件

从配置文件中读取是有用的,但有时您希望存储在运行时所做的所有修改。为此,提供了一系列命令,每个命令都有自己的用途:

  • WriteConfig-将当前 viper 配置写入预定义的路径(如果存在)。如果没有预定义的路径就会出错。将覆盖当前配置文件(如果存在)。
  • SafeWriteConfig-将当前 viper 配置写入预定义的路径。如果没有预定义的路径就会出错。不会覆盖当前配置文件(如果存在)。
  • WriteConfigAs-将当前 viper 配置写入给定的文件路径。将覆盖给定的文件(如果存在)。
  • SafeWriteConfigAs-将当前 viper 配置写入给定的文件路径。不会覆盖给定的文件(如果存在)。

As a rule of the thumb, everything marked with safe won't overwrite any file, but just create if not existent, whilst the default behavior is to create or truncate.

根据经验,所有标记为 safe 的文件都不会覆盖任何文件,只是创建(如果不存在的话) ,而默认行为是创建或截断。

A small examples section:

viper.WriteConfig() // writes current config to predefined path set by 'viper.AddConfigPath()' and 'viper.SetConfigName'
viper.SafeWriteConfig()
viper.WriteConfigAs("/path/to/my/.config")
viper.SafeWriteConfigAs("/path/to/my/.config") // will error since it has already been written
viper.SafeWriteConfigAs("/path/to/my/.other_config")

监视和重新读取配置文件

Viper 支持让应用程序在运行时实时读取配置文件的能力。

需要重新启动服务器才能使配置生效的日子已经一去不复返了,使用 viper 的应用程序可以在运行时读取配置文件的更新,而且不会错过任何一次更新。

只需告诉 viper 实例监视 Config。您还可以为 Viper 提供一个函数,以便在每次发生更改时运行该函数。

确保在调用 WatchConfig ()之前添加了所有的 configPath

viper.OnConfigChange(func(e fsnotify.Event) {
	fmt.Println("Config file changed:", e.Name)
})
viper.WatchConfig()

配置文件实时加载实操

package main

import (
	"fmt"
	"net/http"

	"github.com/fsnotify/fsnotify"
	"github.com/gin-gonic/gin"

	"github.com/spf13/viper"
)

func main() {
	// 设置默认值
	viper.SetDefault("fileDir", "./")
	// 读取配置文件
	viper.SetConfigFile("./config.yaml")  // 指定配置文件路径
	viper.SetConfigName("config")         // 配置文件名称(无扩展名)
	viper.SetConfigType("yaml")           // 如果配置文件的名称中没有扩展名,则需要配置此项
	viper.AddConfigPath("/etc/appname/")  // 查找配置文件所在的路径
	viper.AddConfigPath("$HOME/.appname") // 多次调用以添加多个搜索路径
	viper.AddConfigPath(".")              // 还可以在工作目录中查找配置

	err := viper.ReadInConfig() // 查找并读取配置文件
	if err != nil {             // 处理读取配置文件的错误
		panic(fmt.Errorf("Fatal error config file: %s \n", err))
	}

	// 实时监控配置文件的变化 WatchConfig 开始监视配置文件的更改。
	viper.WatchConfig()
	// OnConfigChange设置配置文件更改时调用的事件处理程序。
	// 当配置文件变化之后调用的一个回调函数
	viper.OnConfigChange(func(e fsnotify.Event) {
		fmt.Println("Config file changed:", e.Name)
	})

	r := gin.Default()
	r.GET("/version", func(c *gin.Context) {
		// GetString以字符串的形式返回与键相关的值。
		c.String(http.StatusOK, viper.GetString("version"))
	})
	r.Run()
}

运行并访问:http://127.0.0.1:8080/version

Code/go/viper_demo via 

标签:语言,err,string,配置文件,viper,Go,config,Viper
From: https://www.cnblogs.com/QiaoPengjun/p/17489207.html

相关文章

  • UnfairSugoroku
    [ABC298E]UnfairSugoroku考虑令\(f[A][B][0/1]\)表示第一/二个人投完,一、二两人数字为\(A,B\)的概率。\[f[A][B][0]=\dfrac{1}{P}\sum_{i=1}^Pf[A-i][B][1]\]\[f[A][B][1]=\dfrac{1}{Q}\sum_{i=1}^Qf[A][B-i][0]\]复杂度\(O((N+P)(N+Q)(P+Q))\)。转移到\(A,B\)中有......
  • VSCode输出"Hello, World!"(编写C语言) 脑残版本一看就懂
    第一步,官网下载VSCode1.官网下载好我全部勾选了2.下载这些扩展第一个,第四个是必需的第二步,MinGW-w64官网下载gcc的资源1.下载64位的2.下载好之后解压到设置的特定文件中3.配置环境变量,点击Path添加这行环境,路径是你下载配置环境的路径配置完毕,一路点击确定3.测......
  • C++ STL(algorithm)
    1字符和整数排序#include<iostream>#include<algorithm>usingnamespacestd;voidstl1(){inta[]={-1,9,-34,100,45,2,98,32};intlen=sizeof(a)/sizeof(int);sort(a,a+len);//由小到大排列sort(a,a+len,greater<int>());//由大到小排列}vo......
  • C++ STL(algorithm)
    1字符和整数排序#include<iostream>#include<algorithm>usingnamespacestd;voidstl1(){inta[]={-1,9,-34,100,45,2,98,32};intlen=sizeof(a)/sizeof(int);sort(a,a+len);//由小到大排列sort(a,a+len,greater<int>());//由大到小排列}vo......
  • go语言tcp编程学习
    TCP编程1、网络编程分类包括TCPsocket编程(底层基于tcp/ip协议)和b/s结构的http编程(使用的是http协议,但是底层是tcpsocket实现的)资料:尚硅谷的TCP资料(3卷),可以咸鱼找下资料看下2TCPsocket编程windows查看端口密码:netstat-anb;netstat-an服务器端的处理流程监听端口;接受......
  • 前端学习C语言 - 数组和字节序
    数组本篇主要介绍:一维二维数组、字符数组、数组名和初始化注意点以及字节序。一维数组初始化有以下几种方式对数组初始化://定义一个有5个元素的数组,未初始化inta[5];//定义一个有5个元素的数组,将第一个初始化0,后面几个元素默认初始化为0inta[5]={0};//定义一个有5个元......
  • 数据库-SQL语言
    SQL语言SQL通用语法以分号结尾使用缩进增加可读性不区分大小写,关键字建议大写SQL语言分类DDL语句DDL--表结构--查询DDL--表结构--创建DDL--表结构--数据类型详细的数据类型char和varcharchar--性能好varchar--性能较差日期时间createtableemp(idin......
  • 归并排序算法及C语言实现
    一、归并排序的原理归并排序(MergeSort)是一种基于分治思想的高效排序算法。其核心思想是将待排序的数组分为两个相等的部分,对这两个部分分别进行递归排序,最后将两个有序的子数组合并成一个有序的整体。可见归并排序的时间复杂度为O(nlog2n)。下面我们来详细地介绍一下归并排序的过......
  • C语言基础教程(动态内存分配)
    (文章目录)前言本篇文章来讲解C语言中的动态内存分配,在C语言中动态内存分配经常使用,合理的使用动态内存分配可以帮助我们节省代码空间,当然了不合理的使用可能导致程序的崩溃,或者是内存的泄漏。一、动态内存分配常用函数在C语言中,动态内存分配是一种在程序运行时分配和释放内......
  • C语言基础教程(宏的使用和多文件编程)
    (文章目录)前言这篇文章来给大家讲解一下C语言中的多文件编程,在C语言开发项目的过程中使用多文件编程是必不可少的,使用多文件编程可以方便我们代码的管理和编写,让我们的代码可读性和移植性更高。一、宏的定义和使用在C语言中,宏(Macro)是一种预处理指令,用于在编译阶段进行文本......