最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

B站新一代 golang規(guī)則引擎gengine基礎(chǔ)語法

 更新時間:2023年12月11日 10:41:46   作者:蕭楚河  
這篇文章主要為大家介紹了B站新一代 golang規(guī)則引擎gengine基礎(chǔ)語法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

  • gengine是一款基于golang和AST(抽象語法樹)開發(fā)的規(guī)則引擎,gengine支持的語法是一種自定義的DSL

  • gengine于2020年7月由嗶哩嗶哩(bilibili.com)授權(quán)開源

  • gengine現(xiàn)已應(yīng)用于B站風(fēng)控系統(tǒng)、流量投放系統(tǒng)、AB測試、推薦平臺系統(tǒng)等多個業(yè)務(wù)場景

  • 你也可以將gengine應(yīng)用于golang應(yīng)用的任何需要規(guī)則或指標(biāo)支持的業(yè)務(wù)場景

優(yōu)勢

對比droolsgengine
執(zhí)行模式僅支持順序模式支持順序模式、并發(fā)模式、混合模式,以及其他細(xì)分執(zhí)行模式
規(guī)則編寫難易程度高,與java強相關(guān)低,自定義簡單語法,與golang弱相關(guān)
規(guī)則執(zhí)行性能低、無論是規(guī)則之間還是規(guī)則內(nèi)部,都是順序執(zhí)行高,無論是規(guī)則間、還是規(guī)則內(nèi),都支持并發(fā)執(zhí)行.用戶基于需要來選擇合適的執(zhí)行模式

開源代碼地址

https://github.com/bilibili/gengine

https://github.com/bilibili/gengine

語法

DSL語法

const rule = `
rule "rulename" "rule-describtion" salience  10
begin
//規(guī)則體
end`

如上,gengine DSL完整的語法塊由如下幾個組件構(gòu)成:

  • 關(guān)鍵字rule,之后緊跟"規(guī)則名稱"和"規(guī)則描述",規(guī)則名稱是必須的,但規(guī)則描述不是必須的. 當(dāng)一個gengine實例中有多個規(guī)則時,"規(guī)則名"必須唯一,否則當(dāng)有多個相同規(guī)則名的規(guī)則時,編譯好之后只會存在一個

  • 關(guān)鍵字salience,之后緊跟一個整數(shù),表示的規(guī)則優(yōu)先級,它們?yōu)榉潜仨?數(shù)字越大,規(guī)則優(yōu)先級越高;當(dāng)用戶沒有顯式的指明優(yōu)先級時,規(guī)則的優(yōu)先級未知, 如果多個規(guī)則的優(yōu)先級相同,那么在執(zhí)行的時候,相同優(yōu)先級的規(guī)則執(zhí)行順序未知

  • 關(guān)鍵字begin和end包裹的是規(guī)則體,也就是規(guī)則的具體邏輯

規(guī)則體語法

  • 規(guī)則體的語法支持或執(zhí)行順序,與主流的計算計語言(如golang、java、C/C++等)一致

規(guī)則體支持的運算

  • 支持完整數(shù)值之間的加(+)、減(-)、乘(*)、除(/)四則運算,以及字符串之間的加法

  • 完整的邏輯運算(&&、 ||、 !)

  • 支持比較運算符: 等于(==)、不等于(!=)、大于(>)、小于(<)、大于等于(>=)、小于等于(<=)

  • 支持+=, -=, *=, /=

  • 支持小括號

  • 優(yōu)先級:括號, 非, 乘除, 加減, 邏輯運算(&&,||) 依次降低

規(guī)則體支持的基礎(chǔ)數(shù)據(jù)類型

  • string

  • bool

  • int, int8, int16, int32, int64

  • uint, uint8, uint16,uint32, uint64

  • float32, float64

不支持的特例

  • 不支持直接處理nil,但用戶可以在rule中定義一個變量去接受nil,然后再定義一個函數(shù)去處理nil

  • 為了用戶使用方便,最新版gengine已經(jīng)內(nèi)置了isNil()函數(shù),用戶可以直接使用,用于判斷數(shù)據(jù)是否為nil

規(guī)則體支持的語法

  • 完整的if .. else if .. else 語法結(jié)構(gòu),及其嵌套結(jié)構(gòu)

其他語法大家如有需求可以去官方文檔查看:

https://github.com/bilibili/gengine/wiki/%E8%AF%AD%E6%B3%95

使用案例

package test
import (
  "bytes"
  "fmt"
  "github.com/bilibili/gengine/builder"
  "github.com/bilibili/gengine/context"
  "github.com/bilibili/gengine/engine"
  "github.com/sirupsen/logrus"
  "io/ioutil"
  "strconv"
  "strings"
  "testing"
  "time"
)
//定義想要注入的結(jié)構(gòu)體
type User struct {
  Name string
  Age  int64
  Male bool
}
func (u *User)GetNum(i int64) int64 {
  return i
}
func (u *User)Print(s string){
  fmt.Println(s)
}
func (u *User)Say(){
  fmt.Println("hello world")
}
//定義規(guī)則
const rule1 = `
rule "name test" "i can"  salience 0
begin
    if 7 == User.GetNum(7){
      User.Age = User.GetNum(89767) + 10000000
      User.Print("6666")
    }else{
      User.Name = "yyyy"
    }
end
`
func Test_Multi(t *testing.T){
  user := &User{
    Name: "Calo",
    Age:  0,
    Male: true,
  }
  dataContext := context.NewDataContext()
  //注入初始化的結(jié)構(gòu)體
  dataContext.Add("User", user)
  //init rule engine
  ruleBuilder := builder.NewRuleBuilder(dataContext)
  start1 := time.Now().UnixNano()
    //構(gòu)建規(guī)則
  err := ruleBuilder.BuildRuleFromString(rule1) //string(bs)
  end1 := time.Now().UnixNano()
  logrus.Infof("rules num:%d, load rules cost time:%d", len(ruleBuilder.Kc.RuleEntities), end1-start1 )
  if err != nil{
    logrus.Errorf("err:%s ", err)
  }else{
    eng := engine.NewGengine()
    start := time.Now().UnixNano()
        //執(zhí)行規(guī)則
    err := eng.Execute(ruleBuilder,true)
    println(user.Age)
    end := time.Now().UnixNano()
    if err != nil{
      logrus.Errorf("execute rule error: %v", err)
    }
    logrus.Infof("execute rule cost %d ns",end-start)
    logrus.Infof("user.Age=%d,Name=%s,Male=%t", user.Age, user.Name, user.Male)
  }
}

示例解釋

  • User是需要被注入到gengine中的結(jié)構(gòu)體;結(jié)構(gòu)體在注入之前需要被初始化;結(jié)構(gòu)體需要以指針的形式被注入,否則無法在規(guī)則中改變其屬性值

  • rule1是以字符串定義的具體規(guī)則

  • dataContext用于接受注入的數(shù)據(jù)(結(jié)構(gòu)體、方法等)

  • ruleBuilder用于編譯字符串形式的規(guī)則

  • engine接受ruleBuilder,并以用戶選定的執(zhí)行模式執(zhí)行加載好的規(guī)則

小技巧

  • 通過示例可以發(fā)現(xiàn),規(guī)則的編譯構(gòu)建和執(zhí)行是異步的. 因此,用戶可使用此特性,在不停服的情況下進行更新規(guī)則.

  • 需要注意的是,編譯構(gòu)建規(guī)則是一個CPU密集型的事情,通常只有規(guī)則被用戶更新的時候才去編譯構(gòu)建更新;

  • gengine內(nèi)部針對規(guī)則加載與移除已經(jīng)做了很多的優(yōu)化,gengine pool提供的所有相關(guān)的api也是線程安全且高性能的,因此我們建議您直接使用gengine pool

  • 另外,用戶還可以通過ruleBuilder來進行異步的語法檢測.

如果大家對設(shè)計實現(xiàn)比較感興趣可以通過如下地址查看:

//m.fzitv.net/jiaoben/284935hzu.htm

以上就是B站新一代 golang規(guī)則引擎gengine基礎(chǔ)語法的詳細(xì)內(nèi)容,更多關(guān)于B站go規(guī)則引擎gengine的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解Go語言如何使用xorm實現(xiàn)讀取mysql

    詳解Go語言如何使用xorm實現(xiàn)讀取mysql

    xorm是go語言的常用orm之一,可以用來操作數(shù)據(jù)庫。本文就來和大家聊聊Go語言如何使用xorm實現(xiàn)讀取mysql功能,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-11-11
  • 深入了解GoLang中的工廠設(shè)計模式

    深入了解GoLang中的工廠設(shè)計模式

    這篇文章主要介紹了深入了解GoLang中的工廠設(shè)計模式,工廠模式是一種常用的設(shè)計模式,它屬于創(chuàng)建型模式,它的主要目的是封裝對象的創(chuàng)建過程,將對象的創(chuàng)建過程與對象的使用過程分離,從而提高代碼的可維護性和可擴展性,需要詳細(xì)了解可以參考下文
    2023-05-05
  • Go語言中的map擴容機制

    Go語言中的map擴容機制

    Go語言中的map是一種高效的數(shù)據(jù)結(jié)構(gòu),其擴容機制確保了在大數(shù)據(jù)量情況下的性能,本文介紹了包括擴容觸發(fā)條件、擴容過程和漸進式擴容,感興趣的可以了解一下
    2024-12-12
  • Golang中crypto/ecdsa庫實現(xiàn)數(shù)字簽名和驗證

    Golang中crypto/ecdsa庫實現(xiàn)數(shù)字簽名和驗證

    本文主要介紹了Golang中crypto/ecdsa庫實現(xiàn)數(shù)字簽名和驗證,將從ECDSA的基本原理出發(fā),詳細(xì)解析如何在Go語言中實現(xiàn)數(shù)字簽名和驗證,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • Go語言時間處理必備技巧全解析

    Go語言時間處理必備技巧全解析

    Golang 的時間處理是 Golang 編程中的一個重要方面,它涉及到了時間類型、時間格式化、時間計算、時區(qū)處理以及定時器和超時機制等多個方面。在本文中,我們將從更深入的角度來探討 Golang 的時間處理
    2023-04-04
  • golang協(xié)程與線程區(qū)別簡要介紹

    golang協(xié)程與線程區(qū)別簡要介紹

    這篇文章主要介紹了golang協(xié)程與線程區(qū)別簡要介紹,進程是操作系統(tǒng)資源分配的基本單位,是程序運行的實例,線程是操作系統(tǒng)調(diào)度到CPU中執(zhí)行的基本單位
    2022-06-06
  • Go語言里的結(jié)構(gòu)體文法實例分析

    Go語言里的結(jié)構(gòu)體文法實例分析

    這篇文章主要介紹了Go語言里的結(jié)構(gòu)體文法,實例分析了結(jié)構(gòu)體文法的概念及使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • 使用Go語言生成二維碼并在命令行中輸出

    使用Go語言生成二維碼并在命令行中輸出

    二維碼(QR code)是一種矩陣條碼的標(biāo)準(zhǔn),廣泛應(yīng)用于商業(yè)、移動支付和數(shù)據(jù)存儲等領(lǐng)域,在開發(fā)過程中,我們可能需要在命令行中顯示二維碼,這可以幫助我們快速生成和分享二維碼信息,本文將介紹如何使用Go語言生成二維碼并在命令行中輸出,需要的朋友可以參考下
    2023-11-11
  • Golang基于文件魔數(shù)判斷文件類型的案例代碼

    Golang基于文件魔數(shù)判斷文件類型的案例代碼

    這篇文章主要介紹了Golang基于文件魔數(shù)判斷文件類型,本文介紹了基于文件魔數(shù)判斷文件類型的方法,主要涉及如何ReadSeek讀取文件指定字節(jié)內(nèi)容,然后介紹文件魔數(shù),最后給出示例基于魔數(shù)判斷文件類型,需要的朋友可以參考下
    2023-02-02
  • Go語言map實現(xiàn)順序讀取

    Go語言map實現(xiàn)順序讀取

    當(dāng)我們遍歷 map 時,那就是輸出的鍵值對順序是不確定的,本文主要介紹了Go語言map實現(xiàn)順序讀取, 文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05

最新評論

黄冈市| 桦川县| 丹寨县| 霍州市| 临沭县| 漳州市| 东丰县| 梨树县| 武胜县| 五河县| 林芝县| 射洪县| 扬中市| 且末县| 临安市| 剑川县| 通辽市| 宁德市| 炉霍县| 林芝县| 枣强县| 灌云县| 大田县| 获嘉县| 城步| 石阡县| 镇宁| 布尔津县| 修文县| 白朗县| 和龙市| 汝南县| 古蔺县| 奇台县| 汉川市| 甘泉县| 西盟| 镇巴县| 新邵县| 赤城县| 日照市|