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

golang規(guī)則引擎gengine用法案例

 更新時(shí)間:2024年01月17日 14:20:06   作者:ZHangQL  
這篇文章主要為大家介紹了golang?規(guī)則引擎gengine用法案例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

本文受 golang面試經(jīng)典講解的[Go工具庫]B 站新一代 golang 規(guī)則引擎gengine啟示, 文中的基本用法和作者的細(xì)節(jié)都基本提到了,大家關(guān)心的可以去看下設(shè)計(jì)文檔及作者對比的gopher_lua的對比

本文主要下作者的幾個(gè)案例和用法

Part1 基本使用

package main
import (
 "fmt"
 "github.com/bilibili/gengine/builder"
 "github.com/bilibili/gengine/context"
 "github.com/bilibili/gengine/engine"
 "github.com/sirupsen/logrus"
 "time"
)
func main() {
 TestMulti()
}
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 TestMulti() {
 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()
 //構(gòu)建規(guī)則
 err := ruleBuilder.BuildRuleFromString(rule1) //string(bs)
 end1 := time.Now()
 logrus.Infof("rules num:%d, load rules cost time:%d", len(ruleBuilder.Kc.RuleEntities), end1.Sub(start1).Milliseconds())
 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)
 }
}

 INFO[0000] rules num:1, load rules cost time:5          
6666
10089767
INFO[0000] execute rule cost 97000 ns                   
INFO[0000] user.Age=10089767,Name=Calo,Male=true 

Part2 @name

在規(guī)則體中使用@name,指代的是當(dāng)前規(guī)則名,@name在規(guī)則執(zhí)行時(shí),會(huì)被解析為規(guī)則名字符串(規(guī)則內(nèi)的名字感知)

package main
import (
 "fmt"
 "github.com/bilibili/gengine/builder"
 "github.com/bilibili/gengine/context"
 "github.com/bilibili/gengine/engine"
 "time"
)
func PrintName(name string) {
 fmt.Println(name)
}
/*
*
use '@name',you can get rule name in rule content
*/
const atNameRule = `
rule "測試規(guī)則名稱1" "rule desc"
begin
  va = @name
  PrintName(va)
  PrintName(@name)
end
rule "rule name" "rule desc"
begin
  va = @name
  PrintName(va)
  PrintName(@name)
end
`
func exec() {
 dataContext := context.NewDataContext()
 dataContext.Add("PrintName", PrintName)
 //init rule engine
 ruleBuilder := builder.NewRuleBuilder(dataContext)
 //resolve rules from string
 start1 := time.Now().UnixNano()
 err := ruleBuilder.BuildRuleFromString(atNameRule)
 end1 := time.Now().UnixNano()
 println(fmt.Sprintf("rules num:%d, load rules cost time:%d ns", len(ruleBuilder.Kc.RuleEntities), end1-start1))
 if err != nil {
  panic(err)
 }
 eng := engine.NewGengine()
 start := time.Now().UnixNano()
 // true: means when there are many rules, if one rule execute error,continue to execute rules after the occur error rule
 err = eng.Execute(ruleBuilder, true)
 end := time.Now().UnixNano()
 if err != nil {
  panic(err)
 }
 println(fmt.Sprintf("execute rule cost %d ns", end-start))
}
func main() {
 exec()
}

 rules num:2, load rules cost time:2820000 ns
測試規(guī)則名稱1
測試規(guī)則名稱1
rule name
rule name
execute rule cost 72000 ns

@name 主要是獲取規(guī)則的名字的

Part3 @id

在規(guī)則體中使用@id含義是,如果當(dāng)前的規(guī)則名是可以轉(zhuǎn)化為整數(shù)的字符串,則@id就是規(guī)則名的整數(shù)值,如果規(guī)則名字符串不可轉(zhuǎn)化為整數(shù),則@id的值為0.這個(gè)是為了方便用戶以規(guī)則名作為整型參數(shù)

package main
import (
 "fmt"
 "github.com/bilibili/gengine/builder"
 "github.com/bilibili/gengine/context"
 "github.com/bilibili/gengine/engine"
)
/*
*
use '@id',you can get rule name in rule content
*/
const atIDRule = `
rule "測試規(guī)則名稱1" "rule desc" salience 10
begin
 println(@id)
end
rule " 100 " "rule desc" salience 20
begin
 x = @id
 println(x)
end
`
func TestAtId() {
 dataContext := context.NewDataContext()
 dataContext.Add("println", fmt.Println)
 //init rule engine
 ruleBuilder := builder.NewRuleBuilder(dataContext)
 //resolve rules from string
 err := ruleBuilder.BuildRuleFromString(atIDRule)
 if err != nil {
  panic(err)
 }
 eng := engine.NewGengine()
 err = eng.Execute(ruleBuilder, false)
 if err != nil {
  panic(err)
 }
}
type Data struct {
 M map[string]string
}
func (d *Data) exe() {
 println("hhhh")
}
func main() {
 TestAtId()
}
100
0

Part4 @desc語法

在規(guī)則體內(nèi)獲知當(dāng)前規(guī)則的描述信息,類型為字符串

package main
import (
 "fmt"
 "github.com/bilibili/gengine/builder"
 "github.com/bilibili/gengine/context"
 "github.com/bilibili/gengine/engine"
 "time"
)
/*
*
use '@desc',you can get rule description in rule content
*/
const atDescRule = `
rule "rule name 1" "我是一個(gè)測試用的描述信息1" salience 100
begin
  desc = @desc
  Print(desc)
  Print(@name + " : " + @desc)
end
rule "rule name 2" //"我是描述,desc" salience 10
begin
  desc = @desc
  Print(desc)
  Print(@name + " : " + @desc)
end
`
func main() {
 dataContext := context.NewDataContext()
 // dataContext.Add("Print", PrintName)
 dataContext.Add("Print", fmt.Println)
 //init rule engine
 ruleBuilder := builder.NewRuleBuilder(dataContext)
 //resolve rules from string
 start1 := time.Now().UnixNano()
 err := ruleBuilder.BuildRuleFromString(atDescRule)
 end1 := time.Now().UnixNano()
 println(fmt.Sprintf("rules num:%d, load rules cost time:%d ns", len(ruleBuilder.Kc.RuleEntities), end1-start1))
 if err != nil {
  panic(err)
 }
 eng := engine.NewGengine()
 // true: means when there are many rules, if one rule execute error,continue to execute rules after the occur error rule
 err = eng.Execute(ruleBuilder, true)
 if err != nil {
  panic(err)
 }
}

 rules num:2, load rules cost time:3172000 ns
我是一個(gè)測試用的描述信息1
rule name 1 : 我是一個(gè)測試用的描述信息1

rule name 2 : 

注意如果有//是注釋 無法解析到

Part5 sal

在規(guī)則體內(nèi)獲知當(dāng)前規(guī)則的優(yōu)先級信息,類型為int64

package main
import (
 "fmt"
 "github.com/bilibili/gengine/builder"
 "github.com/bilibili/gengine/context"
 "github.com/bilibili/gengine/engine"
 "time"
)
func main() {
 dataContext := context.NewDataContext()
 dataContext.Add("println", fmt.Println)
 //init rule engine
 ruleBuilder := builder.NewRuleBuilder(dataContext)
 err := ruleBuilder.BuildRuleFromString(`
rule "1" salience 10
begin
 println(@sal)
end
rule "2" 
begin
 println(@sal)
end
`)
 if err != nil {
  panic(err)
 }
 eng := engine.NewGengine()
 start := time.Now().UnixNano()
 // true: means when there are many rules, if one rule execute error,continue to execute rules after the occur error rule
 err = eng.Execute(ruleBuilder, true)
 end := time.Now().UnixNano()
 if err != nil {
  panic(err)
 }
 println(fmt.Sprintf("execute rule cost %d ns", end-start))
}
10
0
execute rule cost 120000 ns

Part6 注釋

支持規(guī)則內(nèi)的單行注釋,注釋以雙斜杠(//)開頭

Part7 自定義變量

用戶自定義變量無需申明類型 規(guī)則內(nèi)定義的變量,只對當(dāng)前規(guī)則可見,對其他規(guī)則不可見(局部變量) 使用dataContext注入的(變量)數(shù)據(jù),對加載到gengine中的所有規(guī)則均可見(全局變量)

Part8 報(bào)錯(cuò)時(shí)行號提示

gengine支持的語法,是完整的DSL語法(也可以當(dāng)作是一門完整的語言),gengine規(guī)則執(zhí)行出錯(cuò)時(shí),gengine會(huì)指出具體的出錯(cuò)在哪一行.盡量幫助用戶在使用gengine的每一個(gè)流程細(xì)節(jié)上,都有絲滑體驗(yàn)

package main
import (
 "fmt"
 "github.com/bilibili/gengine/builder"
 "github.com/bilibili/gengine/context"
 "github.com/bilibili/gengine/engine"
)
var lineNumberRules = `
rule "line_number"  "when execute error,gengine will give out error"
begin
//Println("golang", "hello", "world" )
//取消斜杠注釋,依次測試不同的報(bào)錯(cuò)情況
//if Println("golang", "hello") == 100 {
//  Println("golang", "hello")
//}
ms.X()
end
`
type MyStruct struct {
}
func (m *MyStruct) XX(s string) {
 println("XX")
}
func Println(s1, s2 string) bool {
 println(s1, s2)
 return false
}
func main() {
 dataContext := context.NewDataContext()
 //注入自定義函數(shù)
 dataContext.Add("Println", Println)
 ms := &MyStruct{}
 dataContext.Add("ms", ms)
 ruleBuilder := builder.NewRuleBuilder(dataContext)
 e1 := ruleBuilder.BuildRuleFromString(lineNumberRules)
 if e1 != nil {
  panic(e1)
 }
 eng := engine.NewGengine()
 // true: means when there are many rules, if one rule execute error,continue to execute rules after the occur error rule
 e2 := eng.Execute(ruleBuilder, true)
 if e2 != nil {
  println(fmt.Sprintf("%+v", e2))
 }
}

 [rule: "line_number" executed, error:
 line 12, column 0, code: ms.X(), NOT FOUND Function: X ]

Part9 多級調(diào)用支持

現(xiàn)在已經(jīng)支持了A.B.C形式的三級調(diào)用,但三級以上的調(diào)用則不支持 其他細(xì)節(jié)說明:

1.當(dāng)語法是C,或者a=C, 則C可以為具體值、變量、函數(shù)或方法、結(jié)構(gòu)體(指針)、map、slice、array等, 具體的如 a=100, a = Mp["hello"], a = x, a = getMessage(p1,p2..)等  

2.當(dāng)語法是A.C,或者a=A.C, 則A必須為結(jié)構(gòu)體(指針), C同上, 具體如a = A.Mp["hello"], a = A.Field1, a = A.GetMessage(p1,p2..)等

3.當(dāng)語法是A.B.C,或者a=A.B.C, 則A和B必須為結(jié)構(gòu)體(指針),C同上, 具體如 a = A.B.Mp["hello"], a =A.B.Field1, a= A.B.GetMessage(p1, p2..)等

那么,如果語法為A.B.C時(shí), A.Mp["hello"].C 這種語法是不合法的

package main
import (
 "fmt"
 "github.com/bilibili/gengine/builder"
 "github.com/bilibili/gengine/context"
 "github.com/bilibili/gengine/engine"
)
type B struct {
 Name string
 Mp   map[string]string
 Ar   [5]string
 Sl   []int
}
func (b *B) Meth(s string) {
 println("--->", s)
}
func main() {
 type A struct {
  N  string
  Ma map[string]string
  B  *B
 }
 rule := `
rule "three level call"
begin
 conc{
 A.B.Name = "xiaoMing"
 A.B.Mp["hello"] = "world"
 A.B.Ar[1] = "Calo"
 A.B.Sl[2] = 3
 x = A.B.Sl[0]
 A.B.Meth(A.B.Ar[1])
 A.N = "kakaka"
 A.Ma["a"] = "b"
 }
 println(A.B.Name, A.B.Mp["hello"], A.B.Ar[1], A.B.Sl[2], x, A.N, A.Ma["a"])
 if A.B.Sl[0] == 0 {
  println(true)
 }
end
`
 b := B{
  Name: "",
  Mp:   make(map[string]string),
  Ar:   [5]string{},
  Sl:   make([]int, 6),
 }
 pA := &A{
  N:  "",
  Ma: make(map[string]string),
  B:  &b,
 }
 dataContext := context.NewDataContext()
 dataContext.Add("println", fmt.Println)
 dataContext.Add("A", pA)
 ruleBuilder := builder.NewRuleBuilder(dataContext)
 e := ruleBuilder.BuildRuleFromString(rule)
 if e != nil {
  panic(e)
 }
 gengine := engine.NewGengine()
 e = gengine.Execute(ruleBuilder, true)
 if e != nil {
  panic(e)
 }
 println(pA.B.Name, pA.B.Mp["hello"], pA.B.Ar[1], pA.B.Sl[2])
}

 ---> Calo
xiaoMing world Calo 3 0 kakaka b
true
xiaoMing world Calo 3

以上就是golang 規(guī)則引擎gengine用法案例的詳細(xì)內(nèi)容,更多關(guān)于golang 規(guī)則引擎gengine的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go使用proto3的踩坑實(shí)戰(zhàn)記錄

    Go使用proto3的踩坑實(shí)戰(zhàn)記錄

    這篇文章主要給大家介紹了關(guān)于Go使用proto3的踩坑記錄,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者會(huì)用Go語言具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2023-02-02
  • Go 語言遞歸函數(shù)實(shí)現(xiàn)方法及應(yīng)用場景

    Go 語言遞歸函數(shù)實(shí)現(xiàn)方法及應(yīng)用場景

    遞歸函數(shù)是編程中一種重要的概念,尤其在Go語言中,遞歸被廣泛應(yīng)用于算法設(shè)計(jì)和程序開發(fā)中,本文將詳細(xì)介紹Go語言中的遞歸函數(shù),包括其基本概念、實(shí)現(xiàn)方法以及應(yīng)用場景,感興趣的朋友跟隨小編一起看看吧
    2025-11-11
  • Go語言實(shí)現(xiàn)將中文轉(zhuǎn)化為拼音功能

    Go語言實(shí)現(xiàn)將中文轉(zhuǎn)化為拼音功能

    這篇文章主要為大家詳細(xì)介紹了Go語言中如何實(shí)現(xiàn)將中文轉(zhuǎn)化為拼音功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-01-01
  • golang替換無法顯示的特殊字符(\u0000,?\000,?^@)

    golang替換無法顯示的特殊字符(\u0000,?\000,?^@)

    這篇文章主要介紹了golang替換無法顯示的特殊字符,包括的字符有\(zhòng)u0000,?\000,?^@等,下文詳細(xì)資料,需要的小伙伴可以參考一下
    2022-04-04
  • Golang中的深拷貝與淺拷貝使用

    Golang中的深拷貝與淺拷貝使用

    本文主要介紹了Golang中的深拷貝與淺拷貝使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • golang之?dāng)?shù)據(jù)驗(yàn)證validator的實(shí)現(xiàn)

    golang之?dāng)?shù)據(jù)驗(yàn)證validator的實(shí)現(xiàn)

    這篇文章主要介紹了golang之?dāng)?shù)據(jù)驗(yàn)證validator的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • go swagger生成接口文檔使用教程

    go swagger生成接口文檔使用教程

    這篇文章主要為大家介紹了go swagger生成接口文檔使用教程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Golang實(shí)現(xiàn)AES對稱加密算法實(shí)例詳解

    Golang實(shí)現(xiàn)AES對稱加密算法實(shí)例詳解

    所謂對稱加密是指在加密和解碼時(shí)使用同一密鑰的加密方式,下面這篇文章主要給大家介紹了關(guān)于Golang實(shí)現(xiàn)AES對稱加密算法的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • golang版本切換的實(shí)現(xiàn)

    golang版本切換的實(shí)現(xiàn)

    本文主要介紹了golang版本切換的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-05-05
  • Go語言HTTPServer開發(fā)的六種方式小結(jié)

    Go語言HTTPServer開發(fā)的六種方式小結(jié)

    Golang的Server開發(fā)顯得非常簡單,有很多種方式,本文就介紹了Go語言HTTPServer開發(fā)的六種方式,具有一定的參考價(jià)值,感興趣的可以了解一下
    2021-11-11

最新評論

且末县| 中山市| 陕西省| 宁陕县| 徐闻县| 安平县| 绍兴县| 永丰县| 揭阳市| 平度市| 建水县| 潼关县| 重庆市| 曲麻莱县| 莎车县| 专栏| 公主岭市| 宁海县| 阳春市| 翁牛特旗| 西丰县| 保德县| 偃师市| 射阳县| 宝鸡市| 化隆| 阿克陶县| 盐边县| 衡南县| 大厂| 宁德市| 于田县| 佛山市| 棋牌| 鄯善县| 青田县| 德昌县| 绥德县| 乳源| 连州市| 鄂州市|