# gorule **Repository Path**: microrain/gorule ## Basic Information - **Project Name**: gorule - **Description**: 一个使用Go语言实现的用于表达复杂规则的通用规则框架 - **Primary Language**: Go - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2021-07-20 - **Last Updated**: 2021-07-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README #规则引擎(Go语言实现) ## 背景 规则引擎主要是用于实现规则的定义与执行的框架。 规则本质上就是满足给定的条件之后执行相应的动作。 即 ```规则 := 条件 -> 动作```,其中条件和动作都可以用一个函数表示。 为了能够将规则引擎的规则定义与具体的规则实例化分离,需要使用能够支持匿名函数传参的编程语言。 通过调研发现,支持匿名函数传参的高级语言有:Python、JavaScript、Go。 但是Python的匿名函数只支持lambda,lambda只能定义简单的一行函数,所以不适合; 而JavaScript主要是用于网页端的脚本开发,显然也不合适; Go语言对于匿名函数有很好的支持,而且Go语言的性能接近C语言,所以最终我选择了使用Go语言来实现规则引擎。 ## 规则引擎设计 - 上下文管理器 - 简单规则与复合规则 - 正则表达式规则 - 序列解析规则 ## 使用示例 ### 简单规则 ``` var TitleRule = core.Rule( func(ctx *core.Context) bool { return true }, func(ctx *core.Context) { trialRound := ctx.GetWithDefault("trialRound", "").(string) topCause := ctx.GetWithDefault("topCause", "").(string) docType := ctx.GetWithDefault("docType", "").(string) causes := ctx.GetWithDefault("causes", []string{}).([]string) cause := "" if causes != nil && len(causes) > 0 { cause = causes[0] } accuser := "" accused := "" accuserList := []string{} accusedList := []string{} party := ctx.GetWithDefault("party", []map[string]string{}).([]map[string]string) if party != nil{ for _, partyInfo := range party{ if _, ok := partyInfo["type"];ok{ if arrays.ContainsString([]string{"原告", "申请人", "上诉人", "再审申请人"}, partyInfo["type"]) != -1{ accuserList = append(accuserList, partyInfo["name"]) }else if arrays.ContainsString([]string{"被告", "被申请人", "被上诉人"}, partyInfo["type"]) != -1{ accusedList = append(accusedList, partyInfo["name"]) } } } } title := "" if len(accuserList) >= 2{ accuser = strings.Join(accuserList[0:2], "、") }else{ accuser = strings.Join(accuserList, "、") } if len(accusedList) >= 2{ accused = strings.Join(accusedList[0:2], "、") }else{ accused = strings.Join(accusedList, "、") } if accuser != "" && accused != ""{ title = fmt.Sprintf("%s%s%s", accuser, "与", accused+cause+trialRound+topCause+docType) }else{ title = fmt.Sprintf("%s%s", accuser, accused+cause+trialRound+topCause+docType) } ctx.Set("title", title) }, ) ``` ### 复合规则 ``` // 文书类型 var DocTypeRule = core.OrRule( core.RegexRule( []string{ `(?m),(判决|裁定)如下[::]`, }, func(self *core.RegexRuleStruct, ctx *core.Context) bool { court_consider := ctx.Get("paraDict").(map[string]string)["court_consider"] return self.ReList[0].MatchString(court_consider) }, func(self *core.RegexRuleStruct, ctx *core.Context) { court_consider := ctx.Get("paraDict").(map[string]string)["court_consider"] docType := self.ReList[0].FindStringSubmatch(court_consider)[1] + "书" ctx.Set("docType", docType) }, ), core.RegexRule( []string{ fmt.Sprintf(`(?m)本院[^。]*?主持(调解),(?:双方)?当事人自愿达成%s{0,5}协议`, "[\u4e00-\u9fa5]"), }, func(self *core.RegexRuleStruct, ctx *core.Context) bool { court_consider := ctx.Get("paraDict").(map[string]string)["conciliation_result"] return self.ReList[0].MatchString(court_consider) }, func(self *core.RegexRuleStruct, ctx *core.Context) { court_consider := ctx.Get("paraDict").(map[string]string)["conciliation_result"] docType := self.ReList[0].FindStringSubmatch(court_consider)[1] + "书" ctx.Set("docType", docType) }, ), ) ``` ### 正则表达式规则 ``` // 案号与收案年份 var CaseNumberRule = core.RegexRule( []string{ fmt.Sprintf( `(?m)[\[【[((﹙〔﹝](\d{4})[﹞﹚))〕]】\]]` + `(?:%s+\d*)` + `(?:%s+)` + `(?:[-\d、l—-]+)` + `(?:号(?:之[一二])?|之[一二三]号)`, "[-\u4e00-\u9fa5-()()、]", "[-\u4e00-\u9fa5-()()、]", ), }, func(self *core.RegexRuleStruct, ctx *core.Context) bool { basic := ctx.Get("paraDict").(map[string]string)["basic"] return self.ReList[0].MatchString(basic) }, func(self *core.RegexRuleStruct, ctx *core.Context) { basic := ctx.Get("paraDict").(map[string]string)["basic"] ctx.Set("caseNumber", self.ReList[0].FindString(basic)) caseNumberYear, _ := strconv.ParseInt(self.ReList[0].FindStringSubmatch(basic)[1], 0, 64) ctx.Set("caseNumberYear", caseNumberYear) }, ) ``` ### 序列解析规则 ``` // 段落解析 core.SeqTextTagParser(ctx).AddRule( &basicRule, &partyInfoRule, &trialProgressRule, &plaintiffClaimsRule, &defendantPleaRule, &courtFindRule, &courtConsiderRule, &conciliationResultRule, &judgeRule, ).Parse(ctx) ```