成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

曹大帶我學 Go之如何優雅地指定配置項

開發 后端
最近一個年久失修的庫導致了線上事故,不得不去做一些改進。這個陳年庫的作用是調用第三方的 RPC 拿一些比較重要的配置,業務代碼中有段邏輯會根據讀到的配置調用不同端的下游。

[[411399]]

本文轉載自微信公眾號「碼農桃花源」,作者小X。轉載本文請聯系碼農桃花源公眾號。

你好,我是小X。

曹大最近開 Go 課程了,小X 正在和曹大學 Go。

這個系列會講一些從課程中學到的讓人醍醐灌頂的東西,撥云見日,帶你重新認識 Go。

最近一個年久失修的庫導致了線上事故,不得不去做一些改進。

這個陳年庫的作用是調用第三方的 RPC 拿一些比較重要的配置,業務代碼中有段邏輯會根據讀到的配置調用不同端的下游。如果沒拿到配置,就會默認地調一個兜底下游。恰好這個兜底下游最近新上了一些邏輯,不兼容這種跨端調用,直接把它打掛了。

先拋開這個下游不健壯不談,假設它是健壯的。

陳年庫的問題在于:進程啟動時它會去調一個下游拿數據,之后會定時更新。但如果啟動時調用失敗就直接 panic 了,所以之后也不會定時更新。理論上這個也沒什么問題,服務在初始化時如果檢測到了庫的 panic,進程退出,重啟就好了。

但是阻塞啟動是比較危險的,所以有些服務就會吞掉 panic。于是,整個進程生命周期內這個配置就一直是缺失的狀態。

因為阻塞服務的啟動風險太高,所以當前的狀態是把 panic recover 住了,但是之后這個配置也就一直沒有更新的機會了。而陳年庫其實是可以在后臺靜默更新數據的。

因此我要對陳年庫要做一點改進:如果初始化時拉取配置失敗,不 panic,后臺靜默修復。這個設置要在調用 Init 函數時設置,因為庫就暴露了 Init 和 Get 函數。

但因為這個庫有很多使用方,所以不可能更改函數簽名和現在的行為,否則影響其他人使用。萬一有業務都對這個是強依賴,就是要感知 panic,初始化失敗就進程退出,你改了不就 gg 了。

我們知道,Go 語言里面有可變參數,調用它的時候可以不傳實參,或者傳多個實參。向陳年庫函數的 Init 函數簽名后加一個可變參數:

  1. func Init(a int

變成:

  1. func Init(a int, opts ...optionFunc) 

這樣就不影響已有的用戶了,并且我可以增加更多的設置項。這里的關鍵是 optionFunc 的實現原理是什么?

它其實是一個函數類型,它接受 options 結構體指針:

  1. type optionFunc func(*options) 

再定義一個 options 結構體用于放 bool 型變量 PanicWhenInitFail,表示 Init 失敗后是否 panic:

  1. type options struct { 
  2.  PanicWhenInitFail bool 

再來定義一個導出的函數,用戶傳入 bool 型變量就可以設置 options,而不用定義 options 對象。這種方法美妙的地方就在這里,要多次回味才能感受到:

  1. func WithPanicWhenInitFail() optionFunc { 
  2.  return func(o *options) { 
  3.   o.PanicWhenInitFail = true 
  4.  } 

初始時,Init 函數的實現如下:

  1. func Init(a int) { 
  2.  fmt.Println(a) 

修改后:

  1. func Init(a int, opts ...optionFunc) { 
  2.  fmt.Println(a) 
  3.  
  4.  var gOpt = &options{PanicWhenInitFail: false
  5.  
  6.  for _, opt := range opts { 
  7.   opt(gOpt) 
  8.  } 
  9.  
  10.  fmt.Println(gOpt) 
  11.  

這樣,main 函數就可以非常優雅地設置 PanicWhenInitFail 了:

  1. func main() { 
  2.  Init(8) 
  3.  Init(8, WithPanicWhenInitFail()) 

不管加不加后面的配置,兩種調用方式都可以編譯成功,不會影響現有的用戶,完美。

為什么這篇文章和曹大扯上關系,因為在曹大寫的 mosn/homels[1] 這個庫里也有類似的代碼。當然,本文這種形式很常見,可以算作標配了。不過,有一點點不同之處,曹大定義了一個 interface,不過看起來感覺有點更難懂了。??

  1. // Option holmes option type. 
  2. type Option interface { 
  3.  apply(*options) error 
  4.  
  5. type optionFunc func(*options) error 
  6.  
  7. func (f optionFunc) apply(opts *options) error { 
  8.  return f(opts) 

去 Google 上一查,其實這種形式,叫 Functional Options Pattern,早在 2014 年 Rob Pike 就寫過一篇博文[2]來說這個事,沒幾行代碼,但是真的很優雅。

總結一下,當我們要修改已有的函數時,為了不破壞原有的簽名和行為,可以使用 Functional Options Pattern 的形式增加可變參數,即可以增加設置項,又能兼容已有的代碼。 

好了,這就是今天全部的內容了~ 我是小X,我們下期再見~

 

責任編輯:武曉燕 來源: 碼農桃花源
相關推薦

2021-06-10 09:00:32

Go底層代碼

2021-06-07 10:47:02

GoGoexit函數

2021-08-09 07:47:39

ExtraGoMap

2021-05-27 08:59:09

Go匯編命令

2021-06-01 09:27:53

Ast Go語言

2021-05-20 08:59:47

Go調度本質

2022-01-05 08:56:20

Go火焰圖編程

2021-09-08 08:34:37

Go 文檔Goland

2018-08-20 10:40:09

Redis位圖操作

2021-03-24 10:20:50

Fonts前端代碼

2024-01-30 12:08:31

Go框架停止服務

2022-04-20 20:27:51

Hydra配置文件開發工具

2024-11-13 16:37:00

Java線程池

2023-02-28 08:17:31

Go遠程配置apollo

2020-03-26 11:04:00

Linux命令光標

2021-01-18 13:17:04

鴻蒙HarmonyOSAPP

2021-05-12 22:07:43

并發編排任務

2022-05-13 21:20:23

組件庫樣式選擇器

2021-01-28 14:53:19

PHP編碼開發

2022-05-24 06:07:48

JShack用戶代碼
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 福利视频一区 | 麻豆av免费观看 | 午夜精品久久久久久久久久久久 | 欧美精品一区二区三区在线播放 | 噜噜噜噜狠狠狠7777视频 | 欧美日韩中文在线 | 亚洲成人一区二区在线 | 欧美aaaaaaaa| 三级av免费| 国产欧美精品一区二区色综合朱莉 | 午夜丁香视频在线观看 | 成人做爰www免费看 午夜精品久久久久久久久久久久 | 亚洲欧美日韩精品久久亚洲区 | 国产激情在线 | 97国产一区二区精品久久呦 | 中文字幕在线网 | 久久久久久影院 | 久久久日韩精品一区二区三区 | 亚洲v区| 特黄毛片| 日本黄视频在线观看 | 国产成人精品a视频一区www | 在线观看成年人视频 | 久草资源| 国产精品极品美女在线观看免费 | 国产99免费 | www国产成人免费观看视频 | 福利网址 | 99精品视频在线 | 亚洲精品视频三区 | 99re视频在线 | 日韩在线播放视频 | 久草福利 | 黄色日本视频 | 黄色一级大片在线免费看产 | 亚洲97| 精品粉嫩超白一线天av | 国内精品久久久久久久 | 国产精品 亚洲一区 | 蜜桃一区| 美女天天操 |