Go语言基于Viper封装实现

news2024/11/24 14:42:46

基于Viper的封装

在这里插入图片描述

Viper是什么

Viper是一个用于Go语言应用程序的配置管理库。它提供了一种简单而灵活的方式来处理应用程序的配置,支持多种格式的配置文件,并提供了一组API来读取和使用这些配置。
Viper支持多种配置文件格式,包括JSON、TOML、YAML和HCL等。它还支持环境变量和命令行标志等配置方式。这使得Viper非常适合需要在不同环境中运行(如开发、测试和生产环境)的应用程序,因为可以使用不同的配置文件和设置来管理应用程序的行为。
优点:使用Viper,可以轻松地将配置信息加载到应用程序中,并在需要时获取这些信息。Viper还提供了一些方便的功能,例如默认值、类型转换和键名重映射等,使得配置管理变得更加简单和灵活。

实现Viper的封装

在根目录下创建一个core文件,然后在core文件中创建多一个interal文件,这个interal文件的方法仅能让core里进行调用的,一般可以将一些仅给core内方法使用并且是需要封装的方法放置在内(调取internal包中的方法不需要添加core包名 )。如图大概就是这样的,然后就是定义一个viper的interface,实现内部的GetFileGetFiles两个方法,前者是配置信息,后者是文件夹路径。当然我们也可以使用embed这样方式实现,但是最好本地也实现一个比较稳妥一点!
在这里插入图片描述

interal文件夹代码实现

core/interal/viper_interface.go

type IViper interface {
	// GetFile 获取文件信息
	GetFile(path, filename string) io.Reader
	// GetFiles 获取配置文件夹信息
	GetFiles(dir string) ([]fs.DirEntry, error)
}

core/interal/viper.go

var Viper = new(viper)

type viper struct{}

func (v *viper) GetFile(path, filename string) io.Reader {
	file, err := os.Open(filepath.Join(path, filename))
	if err != nil {
		return nil
	}
	defer func() {
		_ = file.Close()
	}()
	all, err := io.ReadAll(file)
	if err != nil {
		return nil
	}
	return bytes.NewReader(all)
}

func (v *viper) GetFiles(dir string) ([]os.DirEntry, error) {
	entries, err := os.ReadDir(dir)
	if err != nil {
		return nil, errors.Wrapf(err, "[viper][path:%s]获取配置文件夹信息失败!", dir)
	}
	return entries, nil
}

core/interal/vuper_embed.go (实现本地embed标记,当然推荐使用下面本地实现的方法)

var Viper = new(viper)

type viper struct{}

func (v *viper) GetFile(path, filename string) io.Reader {
	file, err := global.Configs.Open(filepath.Join(path, filename))
	if err != nil {
		fmt.Printf("[viper][path:%s][filename:%s]文件不存在!\n", path, filename)
		return nil
	}
	return file
}

func (v *viper) GetFiles(dir string) ([]fs.DirEntry, error) {
	entries, err := global.Configs.ReadDir(dir)
	if err != nil {
		return nil, errors.Wrapf(err, "[viper][embed][dir:%s]获取配置文件夹信息失败!", dir)
	}
	return entries, nil
}

core/viper.go
我这里的config文件夹中的配置yaml格式如:gorm.debug.yaml


var Viper = new(_viper)

type _viper struct{}

// Initialization .
// 优先级: 命令行 > 环境变量 > 默认值
func (c *_viper) Initialization(path ...string) {
	var configs string
	if len(path) == 0 {
		flag.StringVar(&configs, "c", "", "choose configs dir.")
		flag.Parse()
		if configs == "" {
			env := os.Getenv(internal.ConfigsEnv)
			if env == "" { // 判断 internal.ConfigEnv 常量存储的环境变量是否为空
				configs = internal.ConfigsPath
				fmt.Printf("您正在使用配置默认文件夹:%s,configs的文件夹路径为%s\n", internal.ConfigsPath, configs)
			} else {
				configs = env
				fmt.Printf("您正在使用%s环境变量,configs的文件夹路径为%s\n", internal.ConfigsEnv, configs)
			}
		} else { // 命令行参数不为空 将值赋值于configs
			fmt.Printf("您正在使用命令行的-c参数传递的值,configs的文件夹路径为%s\n", configs)
		}
	} else { // path 这个切片大于0,取第一个值赋值到configs
		configs = path[0]
	}

	v := viper.New()
	v.AddConfigPath(configs)

	entries, err := internal.Viper.GetFiles(configs)
	if err != nil {
		fmt.Printf("%+v\n", err)
		return
	}
	for i := 0; i < len(entries); i++ {
		if entries[i].IsDir() { // 忽略配置文件夹里的文件夹
			continue
		}
		filename := entries[i].Name()
		// 分割文件名
		names := strings.Split(filename, ".")
		if len(names) == 3 {
			config := names[0] // 文件名
			mode := names[1] // 模式
			yaml := names[2] // 文件后缀
			if mode != gin.Mode() {
				continue
			}
			// 拼接
			v.SetConfigName(strings.Join([]string{config, mode}, "."))
			v.SetConfigType(yaml)
			reader := internal.Viper.GetFile(configs, filename)
			
			err = v.MergeConfig(reader)
			if err != nil {
				fmt.Printf("[viper][filename:%s][err:%v]配置文件读取失败!\n", filename, err)
				return
			}
			// 读取配置文件
			err = v.ReadInConfig()
			if err != nil {
				fmt.Printf("[viper][filename:%s][err:%v]配置文件读取失败!\n", filename, err)
				continue
			}
			// 反序列化config
			err = v.Unmarshal(&global.Config)
			if err != nil {
				fmt.Printf("[viper][err:%v]反序列化失败!\n", err)
				continue
			}
			v.OnConfigChange(func(in fsnotify.Event) {
				fmt.Printf("[viper][filename:%s]配置文件更新\n", in.Name)
				err = v.Unmarshal(&global.Config)
				if err != nil {
					fmt.Printf("[viper][err:%v]反序列化失败!\n", err)
				}
			})
			v.WatchConfig()
		}
	}
	// 注册到全局
	global.Viper = v
}

根目录下创建embed.go

如果在自己练习的时候已在编辑器中配置了这个embed标记可以忽略上述本地的viper_embed.go文件(如下图配置所示),但是建议不忽略上述的viper_embed.go文件

在这里插入图片描述

package main

// 这些有import导报
// import (......)

func init() {
	global.Configs = configs
}

var (
	//go:embed configs
	configs embed.FS
)

global中引入结构体

global/global.go

var (
	Viper  *viper.Viper
)

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

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

相关文章

C learning_14 指针篇之破解版

目录 1. 指针是什么 指针变量 2. 指针和指针类型 那指针类型的意义是什么&#xff1f; 3. 野指针 规避野指针 4. 指针运算 指针-整数 指针-指针 指针的关系运算(比较指针的大小) 5. 指针和数组 6. 二级指针 7. 指针数组 1. 指针是什么 指针是C语言中一种非常重要的…

2023年美国大学生数学建模竞赛E题光污染解题全过程文档及程序

2023年美国大学生数学建模竞赛 E题 光污染 原题再现&#xff1a; 背景   光污染被用来描述任何过度或不良地使用人造光。我们所说的一些光污染现象包括光侵入、过度照明和光杂波。在大城市&#xff0c;这些现象最容易被观测到的是太阳落山后天空中的一道辉光; 然而&#xf…

网课录屏怎么录?分享3个录制网课方法!

案例&#xff1a;怎样才能录制清晰流畅的网课视频&#xff1f; 【我最近在网上购买了一个配音的课程&#xff0c;每天晚上8点老师会进行讲课&#xff0c;但是课程没有回放。我想通过录屏的方式将课程内容录制下来&#xff0c;那怎样才能录制清晰流畅的网课视频呢&#xff1f;】…

初识Mybatis -- Mybatis入门保姆级教程(一)

文章目录 前言一、认识mybatis1.mybatis是什么2.jdbc缺点3.mybatis优点4.MyBatis框架解决JDBC劣势 二、mybatis入门案例1.需求分析与操作步骤2.创建表tb_user、实体类和Mapper接口3.创建maven模块re_mb_demon4.在pom.xml配置文件中导入相关依赖5. 配置相关文件6.创建并编写模拟…

百汇BCR:十个外汇交易常见问题解析

外汇交易是一种受到市场欢迎的投资方式&#xff0c;参与交易很容易&#xff0c;但想要盈利却很难。特别是一些细节问题容易被忽略&#xff0c;百汇BCR小编整理了十个外汇交易常见问题供有需要的投资者借鉴学习。 问题一、外汇开户需要哪些资料&#xff1f; 个人相关信息资料、…

重新理解RocketMQ Commit Log存储协议

最近突然感觉&#xff1a;很多软件、硬件在设计上是有root reason的&#xff0c;不是by desgin如此&#xff0c;而是解决了那时、那个场景的那个需求。一旦了解后&#xff0c;就会感觉在和设计者对话&#xff0c;了解他们的思路&#xff0c;学习他们的方法&#xff0c;思维同屏…

JSON格式化工具

格式化JSON有多种方式&#xff0c;选两种。 1.在线JSON格式化 我喜欢用这个网站&#xff1a;在线JSON工具 2.Notepad插件 需要插件 - JSON Viewer。 安装方式&#xff1a; 2.1 点击工具栏“插件”-选择“插件管理…”,弹出插件管理窗口&#xff0c;在“可用”tab页&#xf…

一般人不会告诉你的FP独立站低成本运营内幕

不少朋友听说FP独立站盈利比较高之后就兴致勃勃地跟着别人建站、装修、选品……但在此之前有没有仔细想过&#xff0c;一个成功的F牌独立站到底要怎么运营&#xff1f;而且是&#xff0c;怎么低成本运营&#xff1f;现在我就跟大家分享一下&#xff0c;希望有想法入局F牌独立站…

CorelDRAW2023最新v24.4.0.623中文稳定版

图形设计软件CorelDRAW2023最新版下载矢量图形制作工具,CorelDRAW&#xff08;简称CDR&#xff09;是一款专业的图形设计软件。该软件是Corel公司开发的一款功能强大的专业平面设计软件、矢量设计软件、矢量绘图软件。这款矢量图形制作工具软件广泛应用于商标设计、标志制作、封…

史上最全类和对象 ,只要你认真看完C++类和对象,分分钟钟都吊打面试官【 C++】

文章目录 基础篇面向过程和面向对象类的引入类的定义类的访问限定符类的封装类的作用域类的实例化类对象模型如何计算类对象的大小类对象的存储方式猜测对象中包含类的各个成员代码只保存一份&#xff0c;在对象中保存存放代码的地址只保存成员变量&#xff0c;成员函数存放在公…

10.计算机基础-操作系统面试题—计算机系统概述、进程管理

本文目录如下&#xff1a; 计算机基础-操作系统 面试题一、计算机系统概述CPU 内核态 和 用户态 的区别&#xff1f;从 用户态 切换到 内核态 的常见方法&#xff1a; 二、进程管理线程 和 进程 的区别&#xff1f;协程 (goroutine) 和 线程的区别?进程有哪些状态&#xff1f;…

如果一定要在C++和JAVA中选择,是C++还是java?

前言 C和Java都是广泛应用于软件开发领域的高级编程语言。它们都有着各自的优势和适用场景&#xff0c;因此在进行选择时需要考虑到具体的需求和使用情况。 首先&#xff0c;C是一种面向对象的编程语言&#xff0c;它允许程序员直接控制计算机硬件&#xff0c;而且拥有较低的…

【分享】免费并集多个人工智能于一体的在线使用网站

哈喽&#xff0c;大家好&#xff0c;我是木易巷~ 今天来给大家分享一个集ChatGPT、GPT4、Claude等人工智能于一体的在线使用网站——Poe。 地址&#xff1a;https://poe.com 以下是一个汇集了目前热门人工智能工具的网站&#xff0c;只需使用一个神奇的工具&#xff0c;通过邮…

Todoist 的 10 种最佳替代品(功能、优点、缺点、定价)

寻找最好的 Todoist 替代品&#xff1f; Todoist对项目管理者来说并不陌生&#xff0c;它自 2007 年以来就一直很出名&#xff01; ……但是作为老牌的组织类应用程序之一&#xff0c;现在再用它是否会觉得有点不顺手&#xff1f; 虽然它为了更好适应当今的工作节奏&#xf…

java 餐饮培训平台系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

一、源码特点 java 餐饮培训平台系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

Redis学习---05

一、Redis集群搭建&#xff0c;Redis主从复制&#xff0c;读写分离 默认情况下每台redis服务器都是主节点。 (1) 主从复制&#xff1a;是指将一台redis服务器的数据&#xff0c;复制道其他redis服务。前者成为主节点&#xff0c;后者成为从节点。默认情况下每一台redis服务器…

matlab编程基础

1数据结构 1.1常量与变量 变量命名第一个字符必须为字母&#xff0c;变量可以由数字、字母、下划线组成&#xff0c;区分大小写。 常量&#xff1a; 1.2 数值型数据 双精度&#xff1a;64位 智能存储15位左右十进制数 double() 单精度 &#xff1a;32位&#xff0c;single…

C++ 类和对象下 [补充]

文章目录 友元内部类内部类是外部类的天生友元 匿名对象匿名对象的特性 友元 友元函数 重载operator<< 输出自定义类型 比如日期类的这个重载&#xff0c;就是解决类外访问私有变量的例子&#xff0c;设计成了友元函数。 说明&#xff1a; 友元函数可访问类的私有和保护成…

MS31703直流栅极驱动可pin对pin兼容DRV8703

DRV870x-Q1 器件是一款小型单通道 H 桥栅极驱动器&#xff0c;它使用四个外部 N 通道 MOSFET&#xff0c;旨在驱动一个双向刷式直流电机。 PH/EN、独立 H 桥或 PWM 接口允许轻松连接到控制器电路。内部传感放大器提供可调的电流控制。集成的电荷泵可提供 100% 占空比支持&#…

自动化测试 —— Airtest

最近在做APP自动化过程中&#xff0c;有调研Airtest框架的使用&#xff0c;便初步介绍一下Airtest框架的使用&#xff0c;有兴趣的小伙伴&#xff0c;可以一起探讨学习~ (一&#xff09;背景 Airtest是什么&#xff1f; Airtest是一款基于Python的、跨平台的UI自动化测试框架&…