go kratos源碼及配置解析
相關(guān)類圖
項(xiàng)目啟動(dòng)時(shí)一般前置條件為解析配置文件, 我們看下這塊是怎么設(shè)計(jì)的.

流程解釋
- config 實(shí)現(xiàn) config Interface 接口, 初始化reader對(duì)象
- 調(diào)用Load方法, 通過入口注入的不同文件源, 調(diào)用實(shí)現(xiàn)了source interface 對(duì)應(yīng)的Load方法(以file舉例子)
- file 通過 Load 入口, 判斷是目錄還是文件, 執(zhí)行對(duì)應(yīng)的方法, 拿到文件內(nèi)容返回
- config 拿到file返回的內(nèi)容, 交給reader去合并
- reader 根據(jù)文件格式(yml) 轉(zhuǎn)為 map[string]interface{} 結(jié)構(gòu), 并進(jìn)行覆蓋合并, 將結(jié)果存到對(duì)象變量上
- reader 處理完成后, config調(diào)用 file watcher 進(jìn)行文件變更監(jiān)聽, 啟動(dòng)協(xié)程監(jiān)聽
由此可見, config對(duì)象其實(shí)作為入口, 將數(shù)據(jù)生產(chǎn)交給file、env, 將數(shù)據(jù)加工解析交給 reader
代碼案例
init 接收外部參數(shù)定義解析配置文件地址
func init() {
flag.StringVar(&commonconf, "common", "./configs/local", "common config path, eg: -conf config.yaml")
flag.StringVar(&flagconf, "conf", "./configs/local/api", "config path, eg: -conf config.yaml")
flag.Parse()
}
使用config.New初始化文件配置
//初始化配置
//新增兩個(gè)配置源, 文件格式 common and flagconf 路徑
c := config.New(
config.WithSource(
file.NewSource(commonconf),
file.NewSource(flagconf),
),
)
// 關(guān)閉watch相關(guān)的監(jiān)聽器
defer c.Close()
// 加載配置文件
if err := c.Load(); err != nil {
panic(err)
}
//解析配置到bc結(jié)構(gòu)上
var bc conf.Bootstrap
if err := c.Scan(&bc); err != nil {
panic(err)
}
我們看下config.New的實(shí)現(xiàn)
// 初始化解析器, 關(guān)聯(lián)reader對(duì)象, 數(shù)據(jù)交給由reader加工和存儲(chǔ)
func New(opts ...Option) Config {
o := options{
decoder: defaultDecoder,
resolver: defaultResolver,
}
for _, opt := range opts {
opt(&o)
}
return &config{
opts: o,
reader: newReader(o),
}
}
Options 有下面幾個(gè)屬性
type options struct {
sources []Source // 配置源, 由初始化負(fù)責(zé)傳入的source配置源
decoder Decoder // 解析器
resolver Resolver // 變量解析替換
}
執(zhí)行 Load 配置加載
func (c *config) Load() error {
// 因?yàn)槲覀冊(cè)谌肟趥魅氲氖莊ile對(duì)象, 所以執(zhí)行src load的時(shí)候也是file對(duì)象的 load 方法
for _, src := range c.opts.sources {
// 獲取文件內(nèi)容(可能是一個(gè)目錄, 會(huì)存在多個(gè)文件)
kvs, err := src.Load()
if err != nil {
return err
}
for _, v := range kvs {
log.Debugf("config loaded: %s format: %s", v.Key, v.Format)
}
// 合并配置key
if err = c.reader.Merge(kvs...); err != nil {
log.Errorf("failed to merge config source: %v", err)
return err
}
// 調(diào)用file watch, 監(jiān)聽文件變化
w, err := src.Watch()
if err != nil {
log.Errorf("failed to watch config source: %v", err)
return err
}
c.watchers = append(c.watchers, w)
// 異步監(jiān)聽文件變化(調(diào)用對(duì)應(yīng)的watch對(duì)象)
go c.watch(w)
}
// 解析內(nèi)容中是否包含 ${APPID:default} 變量
// 如果在配置文件中存在 APPID: xx 配置, 則進(jìn)行替換
// 否則使用default默認(rèn)值
if err := c.reader.Resolve(); err != nil {
log.Errorf("failed to resolve config source: %v", err)
return err
}
return nil
}
異步watch
func (c *config) watch(w Watcher) {
for {
kvs, err := w.Next()
if err != nil {
if errors.Is(err, context.Canceled) {
log.Infof("watcher's ctx cancel : %v", err)
return
}
time.Sleep(time.Second)
log.Errorf("failed to watch next config: %v", err)
continue
}
// 處理邏輯忽略 .....
c.cached.Range(func(key, value interface{}) bool {
k := key.(string)
v := value.(Value)
if n, ok := c.reader.Value(k); ok && reflect.TypeOf(n.Load()) == reflect.TypeOf(v.Load()) && !reflect.DeepEqual(n.Load(), v.Load()) {
v.Store(n.Load())
if o, ok := c.observers.Load(k); ok {
o.(Observer)(k, v)
}
}
return true
})
}
}
Scan 將配置轉(zhuǎn)換成結(jié)構(gòu)體
var bc conf.Bootstrap
if err := c.Scan(&bc); err != nil {
panic(err)
}以上就是go kratos源碼及配置解析的詳細(xì)內(nèi)容,更多關(guān)于kratos源碼配置的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
基于Go?goroutine實(shí)現(xiàn)一個(gè)簡(jiǎn)單的聊天服務(wù)
對(duì)于聊天服務(wù),想必大家都不會(huì)陌生,因?yàn)樵谖覀兊纳钪薪?jīng)常會(huì)用到,本文我們用?Go?并發(fā)來實(shí)現(xiàn)一個(gè)聊天服務(wù)器,這個(gè)程序可以讓一些用戶通過服務(wù)器向其它所有用戶廣播文本消息,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06
一文帶你了解Go語言標(biāo)準(zhǔn)庫strings的常用函數(shù)和方法
strings?庫包含了許多高效的字符串常用操作的函數(shù)和方法,巧用這些函數(shù)與方法,能極大的提高我們程序的性能。本文就來和大家分享一下Go標(biāo)準(zhǔn)庫strings的常用函數(shù)和方法,希望對(duì)大家有所幫助2022-11-11
Go?Web開發(fā)之Gin多服務(wù)配置及優(yōu)雅關(guān)閉平滑重啟實(shí)現(xiàn)方法
這篇文章主要為大家介紹了Go?Web開發(fā)之Gin多服務(wù)配置及優(yōu)雅關(guān)閉平滑重啟實(shí)現(xiàn)方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
go local history本地歷史恢復(fù)代碼神器
這篇文章主要為大家介紹了go local history本地歷史恢復(fù)代碼神器的使用功能詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01

