<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在Go語言中,可以直接通過flag標準庫來實現該功能。實現邏輯為,如果存在命令列引數,則優先使用命令列引數,否則使用組態檔中的設定引數。
如下:
var ( port string runMode string config string ) func init() { // 獲取命令列引數 err = setupFlag() if err != nil { log.Fatalf("init.setupFlag err: %v", err) } ...... } // 獲取命令列引數 func setupFlag() error { flag.StringVar(&port, "port", "", "啟動埠") flag.StringVar(&runMode, "mode", "", "啟動模式") flag.StringVar(&config, "config", "config/", "指定要使用的組態檔路徑") flag.Parse() return nil }
通過上述程式碼,我們可以通過標準庫flag讀取命令列引數,然後根據其預設值判斷組態檔是否存在。若存在,則對讀取設定的路徑進行變更,程式碼如下:
package setting import "github.com/spf13/viper" type Setting struct { vp *viper.Viper } // 初始化組態檔的基礎屬性 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 }
接下來,對ServerSetting設定項進行覆寫。如果存在,則覆蓋原有的檔案設定,使其優先順序更高,程式碼如下:
// 初始化組態檔 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 }
然後在執行的時候傳入引數即可:
go run main.go -port=8081 -mode=debug -config=configs/
可以將組態檔存放在系統自帶的全域性變數中,如$HOME/conf或/etc/conf中,這樣做的好處是不需要重新自定義一個新的系統環境變數。
一般來說,我們會在程式中內建一些系統環境變數的讀取,其優先順序低於命令列引數,但高於檔案設定。
可以將組態檔這種第三方檔案打包進二進位制檔案中,這樣就不需要過度關注這些第三方檔案了。但這樣做是有一定代價的,因此要注意使用的應用場景,即並非所有的專案都能這樣操作。
首先安裝go-bindata庫,安裝命令如下:
go get -u github.com/go-bindata/go-bindata/...
通過go-bindata庫可以將資料檔案轉換為Go程式碼。例如,常見的組態檔、資原始檔(如Swagger UI)等都可以打包進Go程式碼中,這樣就可以“擺脫”靜態資原始檔了。接下來在專案根目錄下執行生成命令:
go-bindata -o configs/config.go -pkg-configs configs/config.yaml
執行這條命令後,會將 configs/config.yaml 檔案打包,並通過-o 選項指定的路徑輸出到configs/config.go檔案中,再通過設定的-pkg選項指定生成的packagename為configs,接下來只需執行下述程式碼,就可以讀取對應的檔案內容了:
b,_:=configs.Asset("configs/config.yaml")
把第三方檔案打包進二進位制檔案後,二進位制檔案必然增大,而且在常規方法下無法做檔案的熱更新和監聽,必須要重啟並且重新打包才能使用最新的內容,因此這種方式是有利有弊的。
既然要做設定熱更新,那麼首先要知道設定是什麼時候修改的,做了哪些事?因此我們需要對所設定的檔案進行監聽,只有監聽到了,才能知道它做了哪些變更。
開源庫 fsnotify 是用Go語言編寫的跨平臺檔案系統監聽事件庫,常用於檔案監聽,因此我們可以藉助該庫來實現這個功能。
go get -u golang.org/x/sys/... go get -u github.com/fsnotify/fsnotify
fsnotify是基於golang.org/x/sys實現的,並非syscall標準庫,因此在安裝的同時需要更新其版本,確保版本是最新的。
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 }
通過監聽,我們可以很便捷地知道檔案做了哪些變更。進一步來說,我們可以通過對其進行二次封裝,在它的上層實現一些變更動作來完成組態檔的熱更新。
viper開源庫能夠很便捷地實現對檔案的監聽和熱更新。
開啟pkg/setting/section.go檔案,針對過載應用設定項,新增如下處理方法:
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的儲存記錄,以便在重新載入設定的方法中進行二次處理。接下來新增ReloadAllSection方法,重新讀取設定,程式碼如下:
// 讀取所有設定 func (s *Setting) ReadAllSections() error { for k, v := range sections { err := s.ReadSection(k, v) if err != nil { return err } } return nil } // 監聽設定變化 func (s *Setting) WatchSettingChange() { go func() { s.vp.WatchConfig() s.vp.OnConfigChange(func(in fsnotify.Event) { _ = s.ReloadAllSections() }) }() }
最後在pkg/setting/setting.go檔案中新增檔案熱更新的監聽和變更處理,程式碼如下:
// 初始化組態檔的基礎屬性 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方法中起一個協程,再在裡面通過WatchConfig方法對檔案設定進行監聽,並在OnConfigChange方法中呼叫剛剛編寫的過載方法ReloadAllSection來處理熱更新的檔案監聽事件回撥,這樣就可以“悄無聲息”地實現一個檔案設定熱更新了。
OnConfigChange方法的回撥方法形參,其實就是fsnotify。
以上就是Go中的應用設定管理詳解的詳細內容,更多關於Go應用設定管理的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45