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

Go中的應(yīng)用配置管理詳解

 更新時(shí)間:2022年09月02日 10:01:40   作者:?jiǎn)炭? 
這篇文章主要為大家介紹了Go中的應(yīng)用配置管理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

問(wèn)題

  • Go語(yǔ)言在編譯時(shí)不會(huì)將配置文件這類(lèi)第三方文件打包進(jìn)二進(jìn)制文件中
  • 它既受當(dāng)前路徑的影響,也會(huì)因所填寫(xiě)的不同而改變,并非是絕對(duì)可靠的

解決

命令行參數(shù)

在Go語(yǔ)言中,可以直接通過(guò)flag標(biāo)準(zhǔn)庫(kù)來(lái)實(shí)現(xiàn)該功能。實(shí)現(xiàn)邏輯為,如果存在命令行參數(shù),則優(yōu)先使用命令行參數(shù),否則使用配置文件中的配置參數(shù)。

如下:

var (
	port    string
	runMode string
	config  string
)
func init() {	
	// 獲取命令行參數(shù)
	err = setupFlag()
	if err != nil {
		log.Fatalf("init.setupFlag err: %v", err)
	}
    ......
}
// 獲取命令行參數(shù)
func setupFlag() error {
	flag.StringVar(&port, "port", "", "啟動(dòng)端口")
	flag.StringVar(&runMode, "mode", "", "啟動(dòng)模式")
	flag.StringVar(&config, "config", "config/", "指定要使用的配置文件路徑")
	flag.Parse()
	return nil
}

通過(guò)上述代碼,我們可以通過(guò)標(biāo)準(zhǔn)庫(kù)flag讀取命令行參數(shù),然后根據(jù)其默認(rèn)值判斷配置文件是否存在。若存在,則對(duì)讀取配置的路徑進(jìn)行變更,代碼如下:

package setting
import "github.com/spf13/viper"
type Setting struct {
	vp *viper.Viper
}
// 初始化配置文件的基礎(chǔ)屬性
func NewSetting(configs ...string) (*Setting, error) {
	vp := viper.New()
	vp.SetConfigName("config")
	if len(configs) != 0 {
		for _, config := range configs {
			if config != "" {
				vp.AddConfigPath(config)
			}
		}
	} else {
		vp.AddConfigPath("configs/")
	}
	vp.SetConfigType("yaml")
	err := vp.ReadInConfig()
	if err != nil {
		return nil, err
	}
	return &Setting{vp}, nil
}

接下來(lái),對(duì)ServerSetting配置項(xiàng)進(jìn)行覆寫(xiě)。如果存在,則覆蓋原有的文件配置,使其優(yōu)先級(jí)更高,代碼如下:

// 初始化配置文件
func setupSetting() error {
	setting, err := setting2.NewSetting(strings.Split(config, ",")...)
	if err != nil {
		return err
	}
	......
	if port != "" {
		global.ServerSetting.HttpPort = port
	}
	if runMode != "" {
		global.ServerSetting.RunMode = runMode
	}
	return nil
}

然后在運(yùn)行的時(shí)候傳入?yún)?shù)即可:

go run main.go -port=8081 -mode=debug -config=configs/

系統(tǒng)環(huán)境變量

可以將配置文件存放在系統(tǒng)自帶的全局變量中,如$HOME/conf或/etc/conf中,這樣做的好處是不需要重新自定義一個(gè)新的系統(tǒng)環(huán)境變量。

一般來(lái)說(shuō),我們會(huì)在程序中內(nèi)置一些系統(tǒng)環(huán)境變量的讀取,其優(yōu)先級(jí)低于命令行參數(shù),但高于文件配置。

打包進(jìn)二進(jìn)制文件

可以將配置文件這種第三方文件打包進(jìn)二進(jìn)制文件中,這樣就不需要過(guò)度關(guān)注這些第三方文件了。但這樣做是有一定代價(jià)的,因此要注意使用的應(yīng)用場(chǎng)景,即并非所有的項(xiàng)目都能這樣操作。

首先安裝go-bindata庫(kù),安裝命令如下:

go get -u github.com/go-bindata/go-bindata/...

通過(guò)go-bindata庫(kù)可以將數(shù)據(jù)文件轉(zhuǎn)換為Go代碼。例如,常見(jiàn)的配置文件、資源文件(如Swagger UI)等都可以打包進(jìn)Go代碼中,這樣就可以“擺脫”靜態(tài)資源文件了。接下來(lái)在項(xiàng)目根目錄下執(zhí)行生成命令:

go-bindata -o configs/config.go -pkg-configs configs/config.yaml

執(zhí)行這條命令后,會(huì)將 configs/config.yaml 文件打包,并通過(guò)-o 選項(xiàng)指定的路徑輸出到configs/config.go文件中,再通過(guò)設(shè)置的-pkg選項(xiàng)指定生成的packagename為configs,接下來(lái)只需執(zhí)行下述代碼,就可以讀取對(duì)應(yīng)的文件內(nèi)容了:

b,_:=configs.Asset("configs/config.yaml")

把第三方文件打包進(jìn)二進(jìn)制文件后,二進(jìn)制文件必然增大,而且在常規(guī)方法下無(wú)法做文件的熱更新和監(jiān)聽(tīng),必須要重啟并且重新打包才能使用最新的內(nèi)容,因此這種方式是有利有弊的。

配置熱更新

開(kāi)源的fsnotify

既然要做配置熱更新,那么首先要知道配置是什么時(shí)候修改的,做了哪些事?因此我們需要對(duì)所配置的文件進(jìn)行監(jiān)聽(tīng),只有監(jiān)聽(tīng)到了,才能知道它做了哪些變更。

開(kāi)源庫(kù) fsnotify 是用Go語(yǔ)言編寫(xiě)的跨平臺(tái)文件系統(tǒng)監(jiān)聽(tīng)事件庫(kù),常用于文件監(jiān)聽(tīng),因此我們可以借助該庫(kù)來(lái)實(shí)現(xiàn)這個(gè)功能。

(1)安裝

go get -u golang.org/x/sys/...
go get -u github.com/fsnotify/fsnotify

fsnotify是基于golang.org/x/sys實(shí)現(xiàn)的,并非syscall標(biāo)準(zhǔn)庫(kù),因此在安裝的同時(shí)需要更新其版本,確保版本是最新的。

(2)案例

package main
import (
	"gopkg.in/fsnotify.v1"
	"log"
)
func main() {
	watcher, _ := fsnotify.NewWatcher()
	defer watcher.Close()
	done := make(chan bool)
	go func() {
		for {
			select {
			case event, ok := <-watcher.Events:
				if !ok {
					return
				}
				log.Fatal("event: ", event)
				if event.Op&fsnotify.Write == fsnotify.Write {
					log.Println("modified file:", event.Name)
				}
			case err, ok := <-watcher.Errors:
				if !ok {
					return
				}
				log.Fatal("error:", err)
			}
		}
	}()
	path := "configs/config.yaml"
	_ = watcher.Add(path)
	<-done
}

通過(guò)監(jiān)聽(tīng),我們可以很便捷地知道文件做了哪些變更。進(jìn)一步來(lái)說(shuō),我們可以通過(guò)對(duì)其進(jìn)行二次封裝,在它的上層實(shí)現(xiàn)一些變更動(dòng)作來(lái)完成配置文件的熱更新。

使用viper開(kāi)源庫(kù)實(shí)現(xiàn)熱更新

viper開(kāi)源庫(kù)能夠很便捷地實(shí)現(xiàn)對(duì)文件的監(jiān)聽(tīng)和熱更新。

打開(kāi)pkg/setting/section.go文件,針對(duì)重載應(yīng)用配置項(xiàng),新增如下處理方法:

var sections = make(map[string]interface{})
// 解析配置文件
func (s *Setting) ReadSection(k string, v interface{}) error {
	err := s.vp.UnmarshalKey(k, v)
	if err != nil {
		return err
	}
	if _,ok:=sections[k];!ok{
		sections[k] = v
	}
	return nil
}

首先修改ReadSection方法,增加讀取section的存儲(chǔ)記錄,以便在重新加載配置的方法中進(jìn)行二次處理。接下來(lái)新增ReloadAllSection方法,重新讀取配置,代碼如下:

// 讀取所有配置
func (s *Setting) ReadAllSections() error {
	for k, v := range sections {
		err := s.ReadSection(k, v)
		if err != nil {
			return err
		}
	}
	return nil
}
// 監(jiān)聽(tīng)配置變化
func (s *Setting) WatchSettingChange()  {
	go func() {
		s.vp.WatchConfig()
		s.vp.OnConfigChange(func(in fsnotify.Event) {
			_ = s.ReloadAllSections()
		})
	}()
}

最后在pkg/setting/setting.go文件中新增文件熱更新的監(jiān)聽(tīng)和變更處理,代碼如下:

// 初始化配置文件的基礎(chǔ)屬性
func NewSetting(configs ...string) (*Setting, error) {
	vp := viper.New()
	vp.SetConfigName("config")
	for _, config := range configs {
		if config != "" {
			vp.AddConfigPath(config)
		}
	}
	vp.SetConfigType("yaml")
	err := vp.ReadInConfig()
	if err != nil {
		return nil, err
	}
    // 加入熱更新
	s := &Setting{vp: vp}
	s.WatchSettingChange()
	return s, nil
}

在上述代碼中,首先在NewSetting方法中起一個(gè)協(xié)程,再在里面通過(guò)WatchConfig方法對(duì)文件配置進(jìn)行監(jiān)聽(tīng),并在OnConfigChange方法中調(diào)用剛剛編寫(xiě)的重載方法ReloadAllSection來(lái)處理熱更新的文件監(jiān)聽(tīng)事件回調(diào),這樣就可以“悄無(wú)聲息”地實(shí)現(xiàn)一個(gè)文件配置熱更新了。

OnConfigChange方法的回調(diào)方法形參,其實(shí)就是fsnotify。

以上就是Go中的應(yīng)用配置管理詳解的詳細(xì)內(nèi)容,更多關(guān)于Go應(yīng)用配置管理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解Golang的GC三色標(biāo)記法

    詳解Golang的GC三色標(biāo)記法

    這篇文章主要為大家介紹了Golang的GC三色標(biāo)記法,文中有詳細(xì)的實(shí)現(xiàn)過(guò)程供大家參考,對(duì)大家的學(xué)習(xí)或工作有一定幫助,感興趣的可以跟著小編一來(lái)看看
    2023-05-05
  • golang中單向channel的語(yǔ)法介紹

    golang中單向channel的語(yǔ)法介紹

    通過(guò)消息來(lái)共享數(shù)據(jù)是golang的一種設(shè)計(jì)哲學(xué),channel則是這種哲理的體現(xiàn)。下面這篇文章主要給大家介紹了關(guān)于golang中單向channel語(yǔ)法的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面來(lái)一起看看吧。
    2017-07-07
  • 一文搞懂Golang?值傳遞還是引用傳遞

    一文搞懂Golang?值傳遞還是引用傳遞

    最多人犯迷糊的就是?slice、map、chan?等類(lèi)型,都會(huì)認(rèn)為是?“引用傳遞”,從而認(rèn)為?Go?語(yǔ)言的?xxx?就是引用傳遞。正因?yàn)樗鼈冞€引用類(lèi)型(指針、map、slice、chan等這些),這樣就可以修改原內(nèi)容數(shù)據(jù),這篇文章主要介紹了Golang?值傳遞還是引用傳遞,需要的朋友可以參考下
    2023-01-01
  • win10下go mod配置方式

    win10下go mod配置方式

    這篇文章主要介紹了win10下go mod配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • 詳解在Go語(yǔ)言單元測(cè)試中如何解決文件依賴(lài)問(wèn)題

    詳解在Go語(yǔ)言單元測(cè)試中如何解決文件依賴(lài)問(wèn)題

    現(xiàn)如今的?Web?應(yīng)用程序往往采用?RESTful?API?接口形式對(duì)外提供服務(wù),后端接口直接向前端返回?HTML?文件的情況越來(lái)越少,所以在程序中操作文件的場(chǎng)景也變少了,在編寫(xiě)單元測(cè)試時(shí),文件就成了被測(cè)試代碼的外部依賴(lài),本文就來(lái)講解下測(cè)試過(guò)程中如何解決文件外部依賴(lài)問(wèn)題
    2023-08-08
  • go-zero接入skywalking實(shí)現(xiàn)鏈路追蹤的詳細(xì)教程

    go-zero接入skywalking實(shí)現(xiàn)鏈路追蹤的詳細(xì)教程

    SkyWalking是一個(gè)開(kāi)源的服務(wù)追蹤系統(tǒng),它專(zhuān)注于分布式系統(tǒng)的可觀測(cè)性和服務(wù)性能分析,它的主要目標(biāo)是幫助開(kāi)發(fā)者理解和優(yōu)化微服務(wù)架構(gòu)中的服務(wù)間交互情況,本文介紹了go-zero接入skywalking鏈路追蹤的詳細(xì)教程,需要的朋友可以參考下
    2024-08-08
  • 深入理解golang的基本類(lèi)型排序與slice排序

    深入理解golang的基本類(lèi)型排序與slice排序

    大家都知道排序有內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部的排序記錄,在排序過(guò)程中需要訪問(wèn)外存。下面就來(lái)詳細(xì)介紹golang的基本類(lèi)型排序與slice排序,有需要的朋友們可以參考借鑒。
    2016-09-09
  • golang修改結(jié)構(gòu)體中的切片值方法

    golang修改結(jié)構(gòu)體中的切片值方法

    這篇文章主要介紹了golang修改結(jié)構(gòu)體中的切片值方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • go語(yǔ)言讀取json并下載高清妹子圖片

    go語(yǔ)言讀取json并下載高清妹子圖片

    前面我們介紹了使用python下載高清妹子圖,作為程序猿,我們當(dāng)然不能只會(huì)一種語(yǔ)言,今天我們就來(lái)使用go語(yǔ)言來(lái)讀取API來(lái)下載妹子圖吧,有需要的宅男們可以參考下。
    2015-03-03
  • go實(shí)現(xiàn)服務(wù)優(yōu)雅關(guān)閉的示例

    go實(shí)現(xiàn)服務(wù)優(yōu)雅關(guān)閉的示例

    本文主要介紹了go實(shí)現(xiàn)服務(wù)優(yōu)雅關(guān)閉的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02

最新評(píng)論

常熟市| 高邑县| 武安市| 镇赉县| 屯留县| 凤翔县| 将乐县| 府谷县| 德兴市| 嘉峪关市| 独山县| 肇源县| 阿坝县| 元朗区| 佳木斯市| 阳西县| 福贡县| 镇沅| 遵化市| 凤阳县| 乌鲁木齐县| 延长县| 太原市| 新巴尔虎右旗| 和林格尔县| 重庆市| 海口市| 苍梧县| 会昌县| 咸阳市| 云霄县| 石屏县| 政和县| 化隆| 大冶市| 城市| 乐都县| 金坛市| 年辖:市辖区| 车致| 双辽市|