簡體   English   中英

如何在 Go 中緩存編譯后的正則表達式

[英]How to cache the compiled regex in Go

下面是我的 golang 代碼。 每次調用驗證方法時,都會執行我的編譯方法。 我只想編譯一次,而不是每次我們調用驗證時。

1)怎么做? 2) 我的想法是創建一個在開始時為 nil 的實例變量。 它會在驗證中被延遲初始化。

if (a != nil) {
  a, err := regexp.Compile(rras.Cfg.WhiteList)
}

但是,如果我將變量聲明為實例變量,

var a *Regexp; // regexp.Compile returns *Regexp

我的編譯器用紅色下划線。 如何解決?

type RRAS struct {
    Cfg       *RRAPIConfig
}

type RRAPIConfig struct {
    WhiteList               string
}

func (rras *RRAS) validate(ctx context.Context) error {
        a, err := regexp.Compile(rras.Cfg.WhiteList)
}

Static 初始化

var whitelistRegexp = regexp.MustCompile(Cfg.WhiteList)

func (rras *RRAS) validate(ctx context.Context) error {
  if !whitelistRegexp.Match(...) {...}
}

這將在導入 package 后立即編譯正則表達式,這通常是在程序啟動時,在 main 方法中的任何代碼執行之前。

好處

  • 如果正則表達式被破壞,您的程序將立即崩潰,這有助於非常快速地找到錯誤。
  • 非常小而干凈的代碼,沒有任何陷阱
  • 無需擔心 go-routines

缺點

  • 潛在的緩慢編譯可能會減慢整個程序(或服務器)的啟動速度
  • 僅當正則表達式為 static 且在啟動時出現時才有效
  • 只有在所有情況下都使用單個正則表達式(或幾個 static 正則表達式)時才有效

同步和緩存

var whitelistR struct{
  rex *regexp.Regexp
  once sync.Once
  err error
}

func (rras *RRAS) validate(ctx context.Context) error {
  whitelistR.once.Do(func() {
    whitelistR.ex, whitelistR.err = regexp.Compile(rras.Cfg.WhiteList)
  })

  if whitelistR.err != nil {
    return fmt.Errorf("could not compile regex: %w", err)
  }

  if !whitelistR.rex.Match(...) {...}
}

這將在第一次調用該方法時 layzily 編譯正則表達式。 sync.Once非常重要,因為它是一個同步點,可以保證對正則表達式的訪問不是競爭條件。 對該方法的每次調用都必須等到第一次編譯 Regexp。 之后同步非常快,因為它只使用原子負載。

您還可以在 main 方法中調用go once.Do(...)以並行初始化正則表達式以加速第一次調用,而不會阻塞其他方法。

好處

  • 程序(或服務器)啟動不受編譯時間的影響
  • 僅在實際需要時才進行編譯
  • 您可以根據需要為 Regexp 動態創建 String,這可以減少二進制文件的大小並加快您的程序
  • 可以在緩存映射中緩存許多不同的正則表達式

缺點

  • Regexp 中的錯誤只會出現在實際使用此方法的測試中,不會出現在啟動時
  • 代碼更復雜(10 行而不是一行)
  • 某些開發人員可能會忘記調用 sync.Once 在另一種方法中並引入難以捕獲的競爭條件
  • 有人可能會嘗試變得聰明並包裝同步。一旦調用 if 並將引入難以捕獲的競爭條件

結論

幾乎總是使用簡單的 static 初始化。 僅當您確定對性能有影響(基准測試)時才使用同步初始化。 同步訪問時,請始終嘗試使用 go 提供的幫助程序(sync.Once、Mutex、RWMutex 等),因為它們經過優化且不易出錯。

推薦讀物:

Go Memory Model詳細同步和最佳實踐

Go Data Race Detector你應該對每個復雜的多例程進行競賽測試 go 程序

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM