一个小例子,给你讲透 Go 配置管理,轻松将其融入到项目中

news2024/12/24 11:31:28

在软件开发中,配置管理是一个不可或缺的部分。无论是开发环境、测试环境还是生产环境,我们都需要一种方法来存储和读取配置信息。

在 Golang 项目中,Viper 是一个非常流行且功能强大的库,用于处理配置文件。下面我会写一些例子,帮助大家快速上手。

什么是 Viper?

不卖关子,直接上 GitHub 地址:https://github.com/spf13/viper 大家可以直接去看 README.md

我简单的描述下,Viper 是一个 Go 语言的配置管理库,它提供了简单而强大的方式来处理应用程序的配置需求。无论是从文件、环境变量还是远程配置中获取配置信息,Viper 都能搞定。

如何使用 Viper?

安装

在终端中运行以下命令:

go get github.com/spf13/viper

基本用法

以下是一个简单的示例,展示如何读取配置文件:

package main

import (
 "fmt"
 "github.com/spf13/viper"
)

func main() {
 // 设置配置文件名称(不包括文件扩展名)
 viper.SetConfigName("config")

 // 设置配置文件类型
 viper.SetConfigType("toml")

 // 添加配置文件搜索路径
 viper.AddConfigPath(".")

 // 读取配置文件
 err := viper.ReadInConfig()
 if err != nil {
  panic(fmt.Errorf("fatal error config file: %w", err))
 }

 // 获取配置项
 message := viper.GetString("message")
 fmt.Println("Message:", message)
}

配置文件示例(config.toml)

message = "Hello, Viper!"

输出

Message: Hello, Viper!

这只是一个基本的用法,但在实际项目开发中,推荐采用绑定到配置结构体的方法。

业务场景

场景一

例如,在涉及 MySQL 和 Redis 的项目中,可能需要在配置文件中设置用户名和密码。这时,采用结构体绑定配置的方法比较清晰,可以参考如下示例。

package main

import (
 "fmt"
 "github.com/spf13/viper"
 "log"
)

type configStructs struct {
 MySQL struct {
  Username string `toml:"username"`
  Password string `toml:"password"`
 } `toml:"mysql"`

 Redis struct {
  Username string `toml:"username"`
  Password string `toml:"password"`
 } `toml:"redis"`
}

func main() {
 // 设置配置文件名称(不包括文件扩展名)
 viper.SetConfigName("config")

 // 设置配置文件类型
 viper.SetConfigType("toml")

 // 添加配置文件搜索路径
 viper.AddConfigPath(".")

 // 读取配置文件
 err := viper.ReadInConfig()
 if err != nil {
  log.Fatal(fmt.Errorf("fatal error config file: %w", err))
 }

 // 将配置文件解析到结构体
 configs := new(configStructs)
 err = viper.Unmarshal(configs)
 if err != nil {
  log.Fatal(fmt.Errorf("fatal error config file: %w", err))
 }

 fmt.Println("MySQL-Username:", configs.MySQL.Username)
 fmt.Println("MySQL-Password:", configs.MySQL.Password)
 fmt.Println("Redis-Username:", configs.Redis.Username)
 fmt.Println("Redis-Password:", configs.Redis.Password)
}

配置文件示例(config.toml)

[mysql]
    username = "mysql"
    password = "mysql_qwerty"

[redis]
    username = "redis"
    password = "redis_qwerty"

输出:

MySQL-Username: mysql
MySQL-Password: mysql_qwerty
Redis-Username: redis
Redis-Password: redis_qwerty

场景二

例如,目标是发布一个包含所有必需配置的独立二进制包,而不将配置文件暴露在项目顶层目录。我们应该如何将配置文件嵌入到二进制文件中,确保它们在运行时可以被正确访问?

改造起来不麻烦,可参考如下示例。

package main

import (
 "bytes"
 _ "embed"
 "fmt"
 "github.com/spf13/viper"
 "log"
)

type configStructs struct {
 MySQL struct {
  Username string `toml:"username"`
  Password string `toml:"password"`
 } `toml:"mysql"`

 Redis struct {
  Username string `toml:"username"`
  Password string `toml:"password"`
 } `toml:"redis"`
}

var (
 //go:embed config.toml
 configFile []byte
)

func main() {
 // 设置配置文件名称(不包括文件扩展名)
 viper.SetConfigName("config")

 // 设置配置文件类型
 viper.SetConfigType("toml")

 // 添加配置文件搜索路径
 viper.AddConfigPath(".")

 // 读取配置文件
 err := viper.ReadConfig(bytes.NewReader(configFile))
 if err != nil {
  log.Fatal(fmt.Errorf("fatal error config file: %w", err))
 }

 // 将配置文件解析到结构体
 configs := new(configStructs)
 err = viper.Unmarshal(configs)
 if err != nil {
  log.Fatal(fmt.Errorf("fatal error config file: %w", err))
 }

 fmt.Println("MySQL-Username:", configs.MySQL.Username)
 fmt.Println("MySQL-Password:", configs.MySQL.Password)
 fmt.Println("Redis-Username:", configs.Redis.Username)
 fmt.Println("Redis-Password:", configs.Redis.Password)
}

输出:

MySQL-Username: mysql
MySQL-Password: mysql_qwerty
Redis-Username: redis
Redis-Password: redis_qwerty

代码封装

目前,示例代码都是直接在 main 函数中编写的。

为了提高代码的可维护性和可重用性,我们将这些配置相关的代码封装成一个独立的 configs 包。

package configs

import (
 "bytes"
 _ "embed"
 "fmt"
 "github.com/spf13/viper"
 "log"
)

// ConfigStructs 定义了配置文件的结构
type ConfigStructs struct {
 MySQL struct {
  Username string `toml:"username"`
  Password string `toml:"password"`
 } `toml:"mysql"`

 Redis struct {
  Username string `toml:"username"`
  Password string `toml:"password"`
 } `toml:"redis"`
}

var (
 // 配置结构体的实例
 config = new(ConfigStructs)

 //go:embed config.toml
 configFile []byte
)

func init() {
 // 设置配置文件名称(不包括文件扩展名)
 viper.SetConfigName("config")

 // 设置配置文件类型
 viper.SetConfigType("toml")

 // 添加配置文件搜索路径
 viper.AddConfigPath(".")

 // 读取配置文件
 err := viper.ReadConfig(bytes.NewReader(configFile))
 if err != nil {
  log.Fatal(fmt.Errorf("fatal error config file: %w", err))
 }

 // 将配置文件解析到结构体
 err = viper.Unmarshal(config)
 if err != nil {
  log.Fatal(fmt.Errorf("fatal error config file: %w", err))
 }
}

// Get 获取配置项
func Get() ConfigStructs {
 return *config
}

使用 configs 包:

import (
 "项目名称/pkg/configs"
 "fmt"
)

// 获取配置
fmt.Println("MySQL-Username:", configs.Get().MySQL.Username)
fmt.Println("MySQL-Password:", configs.Get().MySQL.Password)
fmt.Println("Redis-Username:", configs.Get().Redis.Username)
fmt.Println("Redis-Password:", configs.Get().Redis.Password)

输出:

MySQL-Username: mysql
MySQL-Password: mysql_qwerty
Redis-Username: redis
Redis-Password: redis_qwerty

到这,相信已经对 Viper 有了全面的了解,并能够在自己的 Go 项目中灵活应用。

d09bd78c1de30ebd47713987e535fc5e.jpeg

f8ee65659f2618349314aa1ff8eb8311.png

a7ed7f73b6faef45ea82bbc110098f51.jpeg

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

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

相关文章

C++第三节入门 - 引用详解

引用 引用可以对别名进行引用&#xff01; #include<iostream> using namespace std;int main() {int a 0; // 李逵int& b a; // 铁牛int& c b; // 在铁牛的基础上取名为黑旋风return 0; } 引用的特性&#xff1a; 引用在定义的时候必须初始化&…

『功能项目』单例模式框架【37】

我们打开上一篇36C#拓展 - 优化冗余脚本的项目&#xff0c; 本章要做的事情是编写单例模式基类&#xff0c;让继承其基类的子类在运行时只存在一个&#xff0c;共有两个单例基类框架&#xff0c;分别是不继承MonoBehaviour的单例和继承MonoBehaviour的单例框架 首先编写不继承…

【最新华为OD机试E卷-支持在线评测】跳马(200分)多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-E/D卷的三语言AC题解 💻 ACM金牌🏅️团队| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试E卷,全、新、准,题目覆盖率达 95% 以上,支持…

LabVIEW重构其他语言开发的旧系统

在面对一个运行已久、代码不清晰的项目时&#xff0c;如果该项目涉及复杂的通讯协议&#xff08;如串口和488通讯&#xff09;&#xff0c;重新开发并优化成LabVIEW版本可以极大提升系统的易用性和维护性。为了确保通讯协议的顺利解析和移植&#xff0c;借助专业工具分析现有通…

【OpenCV-阈值与平滑处理】灰度图、HSV、图像阈值、图像平滑处理(方框滤波、均值滤波、高斯滤波、中值滤波)

1 灰度图 import cv2 # 导入 OpenCV 库&#xff0c;用于图像处理 import numpy as np # 导入 NumPy 库&#xff0c;用于数组操作 import matplotlib.pyplot as plt # 导入 Matplotlib 库&#xff0c;用于绘图# %matplotlib inline 是 Jupyter Notebook 特有的魔法命令&…

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台&#xff0c;是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力&#xff0c;在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系…

kitti数据label的2d与3d坐标转为像素坐标方法与教程(代码实现)

文章目录 前言一、kitti标签label坐标转换的主函数1、主函数调用代码2、数据格式示意图二、kitti数据获取1、图像获取2、label标签数据获取3、标定文件数据获取 三、kitti标签坐标转换方法1、集成主函数-labels_boxes2pixel_in_image2、标签3d坐标转像素坐标-compute_box_3d(ob…

Caffenie配合Redis做两级缓存

一、什么是两级缓存 在项目中。一级缓存用Caffeine&#xff0c;二级缓存用Redis&#xff0c;查询数据时首先查本地的Caffeine缓存&#xff0c;没有命中再通过网络去访问Redis缓存&#xff0c;还是没有命中再查数据库。具体流程如下 二、简单的二级缓存实现-v1 目录结构 2…

MySQL——主从复制、读写分离

目录 前言 一、MySQL主从复制的概述 1、MySQL主从复制的概念 2、Mysql主从复制功能和使用场景 2.1、Mysql主从复制功能 2.2、Mysql主从复制使用场景 3、MySQL支持的复制类型 3.1、基于语句的复制 3.2、基于行的复制 3.3、混合复制 4、主从复制的工作过程 5、MySQL三…

iOS 15推出后利用邮件打开率的7种方法

自从苹果在2021年底推出iOS 15以来&#xff0c;邮件打开率就一直是一个让人头疼的指标。 Klaviyo市场情报主管Mindy Regnell表示&#xff1a;“对于启用了Apple邮件隐私保护&#xff08;MPP&#xff09;的用户来说&#xff0c;苹果会打开这些邮件并预先下载内容到他们的服务器…

2024年“华为杯”第二十一届中国研究生数学建模竞赛(附2004-2023年优秀论文合集)

中国研究生数学建模竞赛&#xff08;以下简称“竞赛”&#xff09;是教育部学位管理与研究生教育司指导&#xff0c;中国学位与研究生教育学会、中国科协青少年科技中心主办的“中国研究生创新实践系列大赛”主题赛事之一。本届比赛报名时间为&#xff1a;2024年6月1日&#xf…

数据结构——线性表(静态链表、循环链表以及双向链表)

1、静态链表 用数组描述的链表叫做静态链表&#xff0c;这种描述方法叫做游标实现法。 静态链表需要对数组的第一个和最后一个元素作为特殊元素处理&#xff0c;不存数据。 最后一个指向第一个有数据的下标地址&#xff0c;第一个游标指向第一个没有数据的下标地址。 我们对…

[译] 大模型推理的极限:理论分析、数学建模与 CPU/GPU 实测(2024)

译者序 本文翻译自 2024 年的一篇文章&#xff1a; LLM inference speed of light&#xff0c; 分析了大模型推理的速度瓶颈及量化评估方式&#xff0c;并给出了一些实测数据&#xff08;我们在国产模型上的实测结果也大体吻合&#xff09;&#xff0c; 对理解大模型推理内部工…

职场答案薄

公司做大的过程就是创始人把职责一层层分摊下去的过程&#xff0c;公司里的各级领导在招聘时的原始诉求都是一样的&#xff0c;就是招到可以帮自己分担一部分工作的人&#xff0c;然后自己好集中精力去做更重要的工作 如何去做运营 1.流程制度&#xff08;三个目的&#xff1a;…

AI边缘计算在安防领域的智能化革新:赋能安防系统的智能化升级

随着人工智能&#xff08;AI&#xff09;和边缘计算技术的快速发展&#xff0c;两者在安防视频领域的应用日益广泛&#xff0c;为传统安防系统带来了革命性的变革。AI边缘计算技术通过将AI算法和模型部署在边缘设备上&#xff0c;实现了数据处理和智能决策的即时响应&#xff0…

FuTalk设计周刊-Vol.073

#AI漫谈 热点捕手 1.Midjourney 样式分享网站 群里设计师创建的 Midjourney 风格网站&#xff0c;用来收集高质量 Sref Codes&#xff0c;展示示例图并且展示风格关键词&#xff0c;使用场景&#xff0c;以及示例提示词&#xff0c;作者称会持续更新 链接https://aiartsecre…

【Java】String StringBuffer与StringBuilder(实操+面试+记忆方法)

Java系列文章目录 补充内容 Windows通过SSH连接Linux 第一章 Linux基本命令的学习与Linux历史 文章目录 Java系列文章目录一、前言二、学习内容&#xff1a;三、问题描述四、解决方案&#xff1a;4.1 代码学习与性能测试4.1.1 代码4.1.2 性能测试结果 4.2 区别 五、总结&#…

uniapp升级Vue3:避坑指南与步骤详解

为什么要升级到 Vue3 Vue3 是 Vue.js 的最新版本&#xff0c;相比 Vue2&#xff0c;它带来了许多改进和新特性&#xff0c;比如更小的包体积、更好的性能、更强大的组合式 API 等。通过升级到 Vue3&#xff0c;我们可以享受到这些新特性带来的好处&#xff0c;提升项目的开发效…

全国-住宅区AOI数据

数据量级&#xff1a;54万&#xff0c;更新时间&#xff1a;2024年3月 覆盖字段&#xff1a; 名称&#xff0c;地址&#xff0c;经纬度&#xff0c;一级分类&#xff0c;二级分类&#xff0c;三级分类&#xff0c;默认图片&#xff0c;AOI围栏 数据来源于&#xff1a;魔行观察…

从知识孤岛到知识共享:内部知识库如何促进团队协作

在当今快速变化的商业环境中&#xff0c;企业内部的知识管理和协作能力成为决定其竞争力的关键因素之一。然而&#xff0c;许多企业面临着“知识孤岛”的困境&#xff0c;即各部门和团队之间信息交流不畅&#xff0c;知识和经验难以有效传递和共享&#xff0c;导致资源浪费、决…