<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【必看】Go 怎么處理項(xiàng)目配置文件?

          共 2889字,需瀏覽 6分鐘

           ·

          2022-05-19 20:24

          前言

          我們在寫應(yīng)用時(shí),基本都會用到配置文件,從各種 shellnginx 等,都有自己的配置文件。雖然這沒有太多難度,但是配置項(xiàng)一般相對比較繁雜,解析、校驗(yàn)也會比較麻煩。本文就給大家講講我們是怎么簡化配置文件的定義和解析的。

          場景

          如果我們要寫一個(gè) Restful API 的服務(wù),配置項(xiàng)大概有如下內(nèi)容:

          • Host,偵聽的 IP,如果不填,默認(rèn)用 0.0.0.0
          • Port,偵聽的端口,必填,只能是數(shù)字,大于等于80,小于65535
          • LogMode,日志模式,只能選 file 或者 console
          • Verbose,看是否輸出詳細(xì)日志,可選,默認(rèn)為 false
          • MaxConns,允許的最大并發(fā)連接數(shù),默認(rèn) 10000
          • Timeout,超時(shí)設(shè)置,默認(rèn) 3s
          • CpuThreshold,設(shè)置 CPU 使用率觸發(fā)系統(tǒng)降載的閾值,默認(rèn) 900,1000m 表示 100%

          之前我們用 json 做配置文件,但是 json 有個(gè)問題,無法加注釋,所以我們后來切換到了 yaml 格式。

          接下來讓我們看看借助 go-zero 怎么來方便的的定義和解析這樣的配置文件~

          定義配置

          首先,我們需要將上述配置需求定義到 Go 結(jié)構(gòu)體里,如下:

          RestfulConf?struct?{
          ????Host?????????string????????`json:",default=0.0.0.0"`
          ????Port?????????int???????????`json:",range=[80,65535)"`
          ????LogMode??????string????????`json:",options=[file,console]"`
          ????Verbose??????bool??????????`json:",optional"`
          ????MaxConns?????int???????????`json:",default=10000"`
          ????Timeout??????time.Duration?`json:",default=3s"`
          ????CpuThreshold?int64?????????`json:",default=900,range=[0:1000]"`
          }

          可以看到,我們對每個(gè)配置項(xiàng)都有一定的定義和限制,其中一些定義如下:

          • default,配置沒填的話,使用該默認(rèn)值,可以看到其中的 3s 會自動(dòng)解析成 time.Duration 類型
          • optional,此項(xiàng)可以不配置,沒有的話,用類型零值
          • range,限定數(shù)字類型,需要在給定的范圍內(nèi)
          • options,限制配置的值只能是給出的這幾個(gè)之一

          并且,一些屬性可以疊加使用,比如:

          • defaultrange 一起使用,就可以既增加了范圍限制,又提供了默認(rèn)值
          • defaultoptions 一起使用,就可以既增加了可選項(xiàng)限制,又提供了默認(rèn)值

          配置文件

          因?yàn)槲覀冊诙x配置的時(shí)候,給了很多的默認(rèn)值,還有使用 optional 指定為可選,所以我們的配置文件里的配置項(xiàng)就相對比較少了,能用默認(rèn)值的就不用寫了,如下:

          #?因?yàn)楹芏喽加心J(rèn)值,所以只需要寫需要指定值和沒有默認(rèn)值的
          Port:?8080
          LogMode:?console
          #?可以讀取環(huán)境變量的值
          MaxBytes:?${MAX_BYTES}

          這里有個(gè)注意點(diǎn),如果配置項(xiàng)的 value 全部是數(shù)字,而你定義的配置類型是 string,比如有人測試密碼經(jīng)常用 123456,但是密碼一般會定義為 string,配置就要寫成如下(只是舉個(gè)例子哈,密碼一般不建議裸寫到配置文件里):

          Password:?"123456"

          這里的雙引號不能少,少了會報(bào) type mismatch 之類的錯(cuò)誤,因?yàn)?yaml 解析器會把不帶雙引號的 123456 解析成 int。

          加載配置文件

          我們有了配置定義(config.go)和配置文件(config.yaml),接下來就是加載配置文件了,加載配置文件有三種方式:

          • 必須加載成功,否則程序退出,我們一般這么用,如果配置不對,程序就無法繼續(xù)了
          //?有錯(cuò)誤直接退出程序
          var?config?RestfulConf
          conf.MustLoad("config.yaml",?&config)

          go-zero 自帶的 goctl 生成的默認(rèn)代碼也是使用 MustLoad 來加載配置文件的

          • 加載配置,并自行判斷是否有 error
          //?自己判斷并處理?error
          var?config?RestfulConf
          //?為了更簡潔,這里的?LoadConfig?后續(xù)會改為?Load,LoadConfig?已被標(biāo)記為?Deprecated
          if?err?:=?conf.LoadConfig("config.yaml",?&config);?err?!=?nil?{
          ????log.Fatal(err)
          }
          • 加載配置并讀取環(huán)境變量
          //?自動(dòng)讀取環(huán)境變量
          var?config?RestfulConf
          conf.MustLoad(configFile,?&config,?conf.UseEnv())

          這里為啥我們需要顯式指定 conf.UseEnv(),因?yàn)槿绻J(rèn)讀取的話,可能在配置里大家寫特定字符的時(shí)候就需要 escape 了,所以默認(rèn)不讀取環(huán)境變量,這個(gè)設(shè)計(jì)也歡迎大家多提提建議哈

          實(shí)現(xiàn)原理

          我們在實(shí)現(xiàn)類似 yaml/json 解析的時(shí)候一般會直接使用 encoding/json 或者對應(yīng)的 yaml 庫,但是對于 go-zero 來說,我們需要在 unmarshal 的時(shí)候有更精確的控制,這就需要我們自己定制 yaml/json 的解析了,完整的代碼實(shí)現(xiàn)在:

          配置文件代碼:https://github.com/zeromicro/go-zero/tree/master/core/conf

          yaml/json 解析代碼:https://github.com/zeromicro/go-zero/tree/master/core/mapping

          這里也充分展示了 reflect 的用法,以及復(fù)雜場景下如何通過單元測試保證代碼的正確性。

          總結(jié)

          我一直比較推薦 Fail Fast 的思想,我們在加載配置文件的時(shí)候也是這樣,一旦有錯(cuò)誤,立馬退出,這樣運(yùn)維在部署服務(wù)時(shí)就會及時(shí)發(fā)現(xiàn)問題,因?yàn)檫M(jìn)程壓根起不來。

          go-zero 的所有服務(wù)的配置項(xiàng)都是通過這樣的方式來加載和自動(dòng)驗(yàn)證的,包括我寫的很多工具的配置也是基于此來實(shí)現(xiàn)的,希望能對你有所幫助!

          項(xiàng)目地址

          https://github.com/zeromicro/go-zero

          歡迎使用 go-zerostar 支持我們!



          推薦閱讀


          福利

          我為大家整理了一份從入門到進(jìn)階的Go學(xué)習(xí)資料禮包,包含學(xué)習(xí)建議:入門看什么,進(jìn)階看什么。關(guān)注公眾號 「polarisxu」,回復(fù)?ebook?獲取;還可以回復(fù)「進(jìn)群」,和數(shù)萬 Gopher 交流學(xué)習(xí)。

          瀏覽 40
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  肏屄网视频 | 大鸡巴视频在线观看 | 国产黄色片在线免费观看 | 全球亚洲精品视频 | 久久免费精品一区二区三区 |