最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

GoLang實(shí)現(xiàn)Viper庫的封裝流程詳解

 更新時(shí)間:2023年05月19日 08:38:18   作者:三杯溫開水  
Viper是一個(gè)用于Go語言應(yīng)用程序的配置管理庫,它提供了一種簡單而靈活的方式來處理應(yīng)用程序的配置,支持多種格式的配置文件,這篇文章主要介紹了GoLang封裝Viper庫的流程,感興趣的同學(xué)可以參考下文

Viper是什么

Viper是一個(gè)用于Go語言應(yīng)用程序的配置管理庫。它提供了一種簡單而靈活的方式來處理應(yīng)用程序的配置,支持多種格式的配置文件,并提供了一組API來讀取和使用這些配置。

Viper支持多種配置文件格式,包括JSON、TOML、YAML和HCL等。它還支持環(huán)境變量和命令行標(biāo)志等配置方式。這使得Viper非常適合需要在不同環(huán)境中運(yùn)行(如開發(fā)、測(cè)試和生產(chǎn)環(huán)境)的應(yīng)用程序,因?yàn)榭梢允褂貌煌呐渲梦募驮O(shè)置來管理應(yīng)用程序的行為。 優(yōu)點(diǎn):使用Viper,可以輕松地將配置信息加載到應(yīng)用程序中,并在需要時(shí)獲取這些信息。Viper還提供了一些方便的功能,例如默認(rèn)值、類型轉(zhuǎn)換和鍵名重映射等,使得配置管理變得更加簡單和靈活。

實(shí)現(xiàn)Viper的封裝

在根目錄下創(chuàng)建一個(gè)core文件,然后在core文件中創(chuàng)建多一個(gè)interal文件,這個(gè)interal文件的方法僅能讓core里進(jìn)行調(diào)用的,一般可以將一些僅給core內(nèi)方法使用并且是需要封裝的方法放置在內(nèi)(調(diào)取internal包中的方法不需要添加core包名 )。如圖大概就是這樣的,然后就是定義一個(gè)viper的interface,實(shí)現(xiàn)內(nèi)部的GetFileGetFiles兩個(gè)方法,前者是配置信息,后者是文件夾路徑。當(dāng)然我們也可以使用embed這樣方式實(shí)現(xiàn),但是最好本地也實(shí)現(xiàn)一個(gè)比較穩(wěn)妥一點(diǎn)!

interal文件夾代碼實(shí)現(xiàn)

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 (實(shí)現(xiàn)本地embed標(biāo)記,當(dāng)然推薦使用下面本地實(shí)現(xiàn)的方法)

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 .
// 優(yōu)先級(jí): 命令行 > 環(huán)境變量 > 默認(rèn)值
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 常量存儲(chǔ)的環(huán)境變量是否為空
				configs = internal.ConfigsPath
				fmt.Printf("您正在使用配置默認(rèn)文件夾:%s,configs的文件夾路徑為%s\n", internal.ConfigsPath, configs)
			} else {
				configs = env
				fmt.Printf("您正在使用%s環(huán)境變量,configs的文件夾路徑為%s\n", internal.ConfigsEnv, configs)
			}
		} else { // 命令行參數(shù)不為空 將值賦值于configs
			fmt.Printf("您正在使用命令行的-c參數(shù)傳遞的值,configs的文件夾路徑為%s\n", configs)
		}
	} else { // path 這個(gè)切片大于0,取第一個(gè)值賦值到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()
		}
	}
	// 注冊(cè)到全局
	global.Viper = v
}

根目錄下創(chuàng)建embed.go

如果在自己練習(xí)的時(shí)候已在編輯器中配置了這個(gè)embed標(biāo)記可以忽略上述本地的viper_embed.go文件(如下圖配置所示),但是建議不忽略上述的viper_embed.go文件

package main
// 這些有import導(dǎo)報(bào)
// import (......)
func init() {
	global.Configs = configs
}
var (
	//go:embed configs
	configs embed.FS
)

global中引入結(jié)構(gòu)體

global/global.go

var (
	Viper  *viper.Viper
)

到此這篇關(guān)于GoLang實(shí)現(xiàn)Viper庫的封裝流程詳解的文章就介紹到這了,更多相關(guān)GoLang Viper庫封裝內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • go中new和make的區(qū)別小結(jié)

    go中new和make的區(qū)別小結(jié)

    new 只分配內(nèi)存,make 用于初始化 slice、map 和 channel,本文詳細(xì)的介紹了go中new和make的區(qū)別小結(jié),感興趣的可以了解一下
    2023-05-05
  • golang實(shí)現(xiàn)循環(huán)隊(duì)列的示例代碼

    golang實(shí)現(xiàn)循環(huán)隊(duì)列的示例代碼

    循環(huán)隊(duì)列是一種使用固定大小的數(shù)組來實(shí)現(xiàn)隊(duì)列的數(shù)據(jù)結(jié)構(gòu),本文主要介紹了golang實(shí)現(xiàn)循環(huán)隊(duì)列的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-07-07
  • Golang中interface的基本用法詳解

    Golang中interface的基本用法詳解

    Go 中接口也是一個(gè)使用得非常頻繁的特性,好的軟件設(shè)計(jì)往往離不開接口的使用,比如依賴倒置原則(通過抽象出接口,分離了具體實(shí)現(xiàn)與實(shí)際使用的耦合)。 今天,就讓我們來了解一下 Go 中接口的一些基本用法
    2023-01-01
  • 一文詳解Golang中的匿名變量

    一文詳解Golang中的匿名變量

    匿名變量是一種特殊類型的變量,可以簡化代碼并提高可讀性,本文將為大家詳細(xì)介紹一下golang中匿名變量的定義、特性和使用方法,需要的可以參考下
    2023-09-09
  • Go語言程序開發(fā)gRPC服務(wù)

    Go語言程序開發(fā)gRPC服務(wù)

    這篇文章主要為大家介紹了Go語言程序開發(fā)gRPC服務(wù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • golang使用grpc+go-kit模擬oauth認(rèn)證的操作

    golang使用grpc+go-kit模擬oauth認(rèn)證的操作

    這篇文章主要介紹了golang使用grpc+go-kit模擬oauth認(rèn)證的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Golang Cron 定時(shí)任務(wù)的實(shí)現(xiàn)示例

    Golang Cron 定時(shí)任務(wù)的實(shí)現(xiàn)示例

    這篇文章主要介紹了Golang Cron 定時(shí)任務(wù)的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • go語言中的Stringer的使用示例詳解

    go語言中的Stringer的使用示例詳解

    Go 語言中的 Stringer 是一個(gè)非常有用的接口,它在標(biāo)準(zhǔn)庫的 fmt 包中定義,Stringer 接口允許類型定義它們的字符串表示方式,這在格式化輸出時(shí)特別有用,這篇文章主要介紹了go語言中的Stringer的使用,需要的朋友可以參考下
    2025-02-02
  • Golang中對(duì)json的優(yōu)雅處理方式

    Golang中對(duì)json的優(yōu)雅處理方式

    這篇文章主要給大家介紹了關(guān)于Golang中對(duì)json的優(yōu)雅處理方式,解析JSON在golang中很麻煩,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • Go語言通過TCP協(xié)議實(shí)現(xiàn)聊天室功能

    Go語言通過TCP協(xié)議實(shí)現(xiàn)聊天室功能

    這篇文章主要為大家詳細(xì)介紹了Go語言中如何通過TCP協(xié)議實(shí)現(xiàn)聊天室功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-04-04

最新評(píng)論

南皮县| 彰化县| 洞口县| 东阿县| 武威市| 大渡口区| 尼玛县| 龙陵县| 白城市| 修文县| 佛学| 新郑市| 东阳市| 那坡县| 大庆市| 黑龙江省| 微博| 久治县| 朔州市| 林州市| 沾益县| 巴青县| 新津县| 合江县| 桐城市| 卓资县| 白水县| 瑞丽市| 湖北省| 张家口市| 西乡县| 惠水县| 揭西县| 金川县| 怀宁县| 伊宁市| 西充县| 江山市| 南澳县| 康保县| 高要市|