精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

曹大帶我學 Go之初識 Ast 的威力

開發 后端
抽象語法樹是編譯過程中的一個中間產物,一般簡單了解一下就行了。但我們可以把 Go 語言的整個 parser 和 ast 包直接拿來用,在一些場景下有很大的威力。

[[402899]]

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

你好,我是小X。

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

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

抽象語法樹是編譯過程中的一個中間產物,一般簡單了解一下就行了。但我們可以把 Go 語言的整個 parser 和 ast 包直接拿來用,在一些場景下有很大的威力。

什么是 ast 呢,我從維基百科上摘錄了一段:

在計算機科學中,抽象語法樹(Abstract Syntax Tree,AST),或簡稱語法樹(Syntax tree),是源代碼語法結構的一種抽象表示。它以樹狀的形式表現編程語言的語法結構,樹上的每個節點都表示源代碼中的一種結構。

核心就是說 ast 能以一種樹的形式表示代碼結構。有了樹結構,就可以對它做遍歷,能干很多事。

假定一個場景

假定一個場景:我們可以從司機平臺的某個接口獲取司機的各種特征,例如:年齡、訂單數、收入、每天駕駛時長、駕齡、平均車速、被投訴次數……數據一般采用 json 來傳遞。

司機平臺的運營小姐姐經常需要搞一些活動,例如選出:

  • 訂單數超過 10000,且駕齡超過 5 年的老司機
  • 每天駕駛時小于 3 小時,且收入超過 500 的高效司機
  • 年齡大于 40,且平均速度大于 70 的“狂野”司機
  • ……

這些規則并不是固定的,經常在變化,但總歸是各種司機特征的組合。

為了簡化,我們選取 2 個特征,并用一個 Driver 結構體來表示:

  1. type Driver struct { 
  2.  Orders         int 
  3.  DrivingYears   int 

為了配合運營搞活動,我們需要根據運營給的規則來判斷一個司機是否符合要求。

如果公司人多,可以安排一個 rd 專門伺候運營小姐姐,每次做活動都來手動修改代碼,也不是不可以。并且其實挺簡單,我們來寫一個示例代碼:

  1. // 從第三方獲取司機特征,json 表示 
  2. func getDriverRemote() []byte { 
  3.  return []byte(`{"orders":100000,"driving_years":18}`) 
  4.  
  5. // 判斷是否為老司機 
  6. func isOldDriver(d *Driver) bool { 
  7.  if d.Orders > 10000 && d.DrivingYears > 5 { 
  8.   return true 
  9.  } 
  10.  return false 
  11.  
  12. func main() { 
  13.  bs := getDriverRemote() 
  14.  var d Driver 
  15.  json.Unmarshal(bs, &d) 
  16.  fmt.Println(isOldDriver(&d)) 

直接來看 main 函數:getDriverRemote 模擬從第三方 RPC 獲取一個司機的特征數據,用 json 表示。接著 json.Unmarshal 來反序列化 Driver 結構體。最后調用 isOldDriver 函數來判斷此司機是否符合運營的規則。

isOldDriver 根據 Driver 結構體的 2 個字段使用 if 語句來判斷此司機是否為老司機。

確實還挺簡單。

但是每次更新規則還得經過一次完整的上線流程,也挺麻煩的。有沒有更簡單的辦法呢?使得我們可以直接解析運營小組姐給我們的一個用字符串表示的規則,并直接返回一個 bool 型的值,表示是否滿足條件。

有的!

接下來就是本文的核心內容,如何使用 ast 來完成同樣的功能。

直觀地理解如何用 ast 解析規則

使用 ast 包提供的一些函數,我們可以非常方便地將如下的規則字符串:

  1. orders > 10000 && driving_years > 5 

解析成一棵這樣的二叉樹:

規則二叉樹

其中,ast.BinaryExpr 代表一個二元表達式,它由 X 和 Y 以及符號 OP 三部分組成。最上面的一個 BinaryExpr 表示規則的左半部分和右半部分相與。

很明顯,左半部分就是:orders > 10000,而右半部分則是:driving_years > 5。神奇的是,左半部分和右半部分恰好又都是一個二元表達式。

左半部分的 orders > 10000 其實也是最小的葉子節點,它可以算出來一個 bool 值。把它拆開來之后,又可以分成 X、Y、OP。X 是 orders,OP 是 ">",Y 則是 "10000"。其中 X 表示一個標識符,是 ast.Ident 類型,Y 表示一個基本類型的字面量,例如 int 型、字符串型……是 ast.BasicLit 類型。

右半部分的 driving_years > 18 也可以照此拆分。

然后,從 json 中取出這個司機的 orders 字段的值為 100000,它比 10000 大,所以左半部分算出來為 true。同理,右半部分算出來也為 true。最后,再算最外層的 "&&",結果仍然為 true。

至此,直接根據規則字符串,我們就可以算出來結果。

如果寫成程序的話,就是一個 dfs 的遍歷過程。如果不是葉子結點,那就是二元表達式結點,那就一定有 X、Y、OP 部分。遞歸地遍歷 X,如果 X 是葉子結點,那就結束遞歸,并計算出 X 的值……

這里再展示一個用 ast 包打印出來的抽象語法樹:

Go 打印 ast

上圖中,1、2、3 表示最外層的二元表達式;4、5、6 則表示左邊這個二元表達式。

結合這張圖,再參考 ast 包的相關結構體 代碼,就非常清晰了。例如 ast.BinaryExpr 的代碼如下:

  1. // A BinaryExpr node represents a binary expression. 
  2. BinaryExpr struct { 
  3.  X     Expr        // left operand 
  4.  OpPos token.Pos   // position of Op 
  5.  Op    token.Token // operator 
  6.  Y     Expr        // right operand 

它有 X、Y、OP,甚至還解析出了 Op 的位置,用 OpPos 表示。

如果你還對實現感興趣,那就繼續看下面的原理分析部分,否則可以直接跳到結尾總結部分。

原理分析

還是用上面那個例子,我們直接寫一個表達式:

  1. orders > 10000 && driving_years > 5 

接下來用 ast 來解析規則并判斷真假。

  1. func main() { 
  2.  m := map[string]int64{"orders": 100000, "driving_years": 18} 
  3.  rule := `orders > 10000 && driving_years > 5` 
  4.  fmt.Println(Eval(m, rule)) 

為了簡單,我們直接用 map 來代替 json,道理是一樣的,僅僅為了方便。

Eval 函數判斷 rule 的真假:

  1. // Eval : 計算 expr 的值 
  2. func Eval(m map[string]int64, expr string) (bool, error) { 
  3.  exprAst, err := parser.ParseExpr(expr) 
  4.  if err != nil { 
  5.   return false, err 
  6.  } 
  7.  
  8.  // 打印 ast 
  9.  fset := token.NewFileSet() 
  10.  ast.Print(fset, exprAst) 
  11.  
  12.  return judge(exprAst, m), nil 

先將表達式解析成 Expr,接著調用 judge 函數計算結果:

  1. // dfs 
  2. func judge(bop ast.Node, m map[string]int64) bool { 
  3.     // 葉子結點 
  4.  if isLeaf(bop) { 
  5.   // 斷言成二元表達式 
  6.   expr := bop.(*ast.BinaryExpr) 
  7.   x := expr.X.(*ast.Ident) // 左邊 
  8.   y := expr.Y.(*ast.BasicLit) // 右邊 
  9.  
  10.   // 如果是 ">" 符號 
  11.   if expr.Op == token.GTR { 
  12.    left := m[x.Name
  13.    right, _ := strconv.ParseInt(y.Value, 10, 64) 
  14.    return left > right 
  15.   } 
  16.   return false 
  17.  } 
  18.  
  19.  // 不是葉子節點那么一定是 binary expression(我們目前只處理二元表達式) 
  20.  expr, ok := bop.(*ast.BinaryExpr) 
  21.  if !ok { 
  22.   println("this cannot be true"
  23.   return false 
  24.  } 
  25.  
  26.  // 遞歸地計算左節點和右節點的值 
  27.  switch expr.Op { 
  28.  case token.LAND: 
  29.   return judge(expr.X, m) && judge(expr.Y, m) 
  30.  case token.LOR: 
  31.   return judge(expr.X, m) || judge(expr.Y, m) 
  32.  } 
  33.  
  34.  println("unsupported operator"
  35.  return false 

judge 使用 dfs 遞歸地計算表達式的值。

遞歸地終止條件是葉子節點:

  1. // 判斷是否是葉子節點 
  2. func isLeaf(bop ast.Node) bool { 
  3.  expr, ok := bop.(*ast.BinaryExpr) 
  4.  if !ok { 
  5.   return false 
  6.  } 
  7.  
  8.  // 二元表達式的最小單位,左節點是標識符,右節點是值 
  9.  _, okL := expr.X.(*ast.Ident) 
  10.  _, okR := expr.Y.(*ast.BasicLit) 
  11.  if okL && okR { 
  12.   return true 
  13.  } 
  14.  
  15.  return false 

總結

今天這篇文章主要講了如何用 ast 包和 parser 包解析一個二元表達式,并見識到了它的威力,利用它可以做成一個非常簡單的規則引擎。

其實利用 ast 包還可以做更多有意思的事情。例如批量把 thrift 文件轉化成 proto 文件、解析 sql 語句并做一些審計……

 

想要更深入的學習,可以看曹大這篇《golang 和 ast》[1],據曹大自己說,他可以在 30 分鐘內完成一個項目的一個 api 的編寫,非常霸氣!不服噴他……

 

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

2021-06-10 09:00:32

Go底層代碼

2021-06-07 10:47:02

GoGoexit函數

2021-05-20 08:59:47

Go調度本質

2022-01-05 08:56:20

Go火焰圖編程

2021-08-09 07:47:39

ExtraGoMap

2021-07-15 08:58:15

指定配置項Go

2021-05-27 08:59:09

Go匯編命令

2023-12-21 07:09:32

Go語言任務

2021-08-31 20:21:11

VitessMySQL分庫

2023-02-28 08:24:49

2023-09-11 06:12:31

盒子模型CSS

2023-10-27 08:33:40

Go語言元編程

2018-03-12 22:13:46

GO語言編程軟件

2021-08-04 07:47:19

HTTP網絡協議

2020-06-05 14:29:07

PythonPandas數據分析

2021-08-30 08:23:34

Go語言進程

2013-04-08 14:46:42

Android學習筆記百度地圖

2020-10-26 09:36:45

Java變量數據

2023-07-31 08:45:10

Shell腳本

2016-12-01 14:16:18

GitSCM配置
點贊
收藏

51CTO技術棧公眾號

国产精品久久久久久久久久东京 | 国产成人综合视频| 免费99精品国产自在在线| 亚洲日本久久久| 高清电影一区| 亚洲精品自拍动漫在线| 黄色99视频| 一级特黄特色的免费大片视频| 欧美精品导航| 中文字幕亚洲精品| 亚洲精品第二页| 久久伊人国产| 欧美日韩一区二区在线 | 日韩欧美福利视频| 麻豆中文字幕在线观看| 五月婷婷免费视频| 国产精品中文字幕一区二区三区| 51精品在线观看| 69av视频在线| 久久五月天小说| 亚洲日本欧美中文幕| 亚洲成a人无码| 日韩黄色在线| 日韩欧美中文第一页| 国产制服91一区二区三区制服| 免费av在线电影| 国产白丝精品91爽爽久久 | 一区二区中文字幕在线观看| 在线一区二区三区四区五区| 老子影院午夜伦不卡大全| 欧美96在线| 国产欧美精品一区二区三区四区| 好看的日韩精品| 亚洲国产视频一区二区三区| 另类小说综合欧美亚洲| 国产成人小视频在线观看| 国产精品99无码一区二区| 午夜久久美女| 欧美www在线| 尤物在线免费视频| 久久理论电影| 色一情一乱一区二区| 亚洲天堂久久新| 台湾佬综合网| 亚洲精品一区在线观看香蕉| 欲求不满的岳中文字幕| 超碰97久久国产精品牛牛| 制服丝袜成人动漫| 污视频网址在线观看| 欧美成人aaa| 欧美日韩国产大片| 天天综合网久久| 欧美性aaa| 精品污污网站免费看| 一级黄色香蕉视频| 亚洲不卡系列| 欧美三级电影精品| 色呦色呦色精品| 欧美影院视频| 精品久久人人做人人爽| 国产精品亚洲一区二区无码| 粉嫩一区二区三区四区公司1| 欧美va亚洲va香蕉在线| 日本精品一二三区| 欧美人与动xxxxz0oz| 精品国产免费人成在线观看| 欧美一级片黄色| 免费看日本一区二区| 亚洲一区二区久久| 黄色精品视频在线观看| 欧美黄污视频| 欧美一区第一页| 日韩欧美一级大片| 激情深爱一区二区| 97超级碰碰| 无码国产精品一区二区免费16| 久久影院午夜论| 色综合视频二区偷拍在线| 久草资源在线| 亚洲mv在线观看| 麻豆传传媒久久久爱| av成人在线播放| 日韩欧美综合在线| 在线免费观看黄色小视频| 国产精品一区二区99| www亚洲精品| 日本系列第一页| 日韩电影在线免费观看| 91性高湖久久久久久久久_久久99| 精品人妻一区二区三区四区不卡| 99久久精品国产毛片| 神马影院午夜我不卡影院| 很黄的网站在线观看| 污片在线观看一区二区| 超碰在线播放91| 99久久香蕉| 中文字幕免费精品一区| 久久久久久久福利| 丝袜美腿高跟呻吟高潮一区| 91久久精品国产91久久| 五月婷婷六月色| 亚洲乱码精品一二三四区日韩在线| 国产原创中文在线观看| 日韩国产91| 亚洲男人的天堂在线| 91高清免费看| 日本亚洲视频在线| 国产乱码精品一区二区三区卡| 91sp网站在线观看入口| 天天色 色综合| 五月天婷婷在线观看视频| 亚洲第一二三区| 欧美日韩xxxxx| 中文字幕免费播放| 99久久免费视频.com| 在线观看污视频| 欧美激情三区| 亚洲热线99精品视频| 精品无码免费视频| 狠狠久久亚洲欧美| 五月天亚洲综合情| 成人欧美magnet| 精品国产乱码久久久久久牛牛| 精品一区二区6| 免费日韩av片| 国内成+人亚洲| caoprom在线| 日韩欧美一区二区在线视频| 蜜桃视频最新网址| 免费一级片91| 少妇特黄a一区二区三区| 看黄在线观看| 亚洲激情自拍图| 国产在线拍揄自揄拍无码视频| 激情欧美一区二区三区在线观看| 先锋影音一区二区三区| 精品国产免费观看| 韩国福利在线| 亚洲国产aⅴ天堂久久| 想看黄色一级片| 日韩欧美综合| 国产不卡在线观看| 日韩三级电影网| 岛国av午夜精品| 黄色av网址在线观看| 黑人一区二区| 91久久偷偷做嫩草影院| 亚洲wwwww| 日韩欧美精品三级| 欧美日韩精品在线观看视频 | 久久久精品人妻一区二区三区| 99久久99久久精品国产片桃花| 国产极品精品在线观看| 免费毛片在线| 在线精品视频免费观看| 国产人妻一区二区| 日日噜噜夜夜狠狠视频欧美人| 欧美不卡在线一区二区三区| 不卡av影片| 永久免费精品影视网站| 亚洲手机在线观看| 中文字幕一区三区| 伦伦影院午夜理论片| 欧美精品国产一区二区| 国产在线精品一区二区三区| 在线免费看h| 国产一区二区久久精品| 在线视频 中文字幕| 亚洲欧洲另类国产综合| 激情小说欧美色图| 日韩视频二区| 色综合久久久久久久久五月| 亚洲精品aaa| 欧美激情第三页| 免费a级毛片在线观看| 欧美日韩免费一区二区三区| 国产高清在线免费观看| 91一区二区在线观看| 久久久精品三级| 亚洲国产老妈| 精品乱色一区二区中文字幕| 日本电影欧美片| 久久成人精品一区二区三区| 国产91免费看| 欧美视频一区二| 欧美人妻精品一区二区免费看| 99国产精品久久久| 少妇一级淫免费播放| 亚洲夜间福利| 天堂社区 天堂综合网 天堂资源最新版 | 久久精品一二三四| 伊人久久亚洲热| 亚洲黄色一区二区三区| 风间由美一区二区av101| 日韩av三级在线观看| av免费网站在线观看| 日韩高清av一区二区三区| 中文字幕有码视频| 亚洲高清免费一级二级三级| 国产精品成人在线视频| 成人丝袜高跟foot| 久久国产这里只有精品| 亚洲一区二区三区四区五区午夜| 一区二区视频在线观看| 免费看久久久| 亚洲综合第一页| 3d性欧美动漫精品xxxx软件| 久久久久久久久久久免费| 午夜国产福利在线| 亚洲免费视频在线观看| 黄色小视频免费观看| 欧美嫩在线观看| 日本熟女毛茸茸| 亚洲国产综合色| 久久嫩草捆绑紧缚| 国产欧美一区二区三区沐欲| 亚洲欧美日韩偷拍| 国产揄拍国内精品对白| 日本新janpanese乱熟| 99精品国产一区二区青青牛奶 | 777色狠狠一区二区三区| 青青操免费在线视频| 一区二区三区影院| 人妻久久一区二区| 国产精品伦一区二区三级视频| 午夜一区二区三区免费| 成人在线视频一区| 肉丝美足丝袜一区二区三区四| 热久久一区二区| 国产免费视频传媒| 国产日韩欧美一区在线| 国产毛片视频网站| 国产精品草草| 中文字幕免费高| 天堂网在线观看国产精品| 日韩av高清| 精品视频国产| 翔田千里亚洲一二三区| 国产成人精品一区二区免费看京| 久久精品二区| 牲欧美videos精品| 久久亚洲国产精品日日av夜夜| 九九热hot精品视频在线播放| 成人激情直播| 国产欧美三级电影| 狠狠色综合网站久久久久久久| 成人资源在线| 韩国成人一区| 亚洲aaa级| 视频一区视频二区视频三区高 | 九九久久九九久久| 牛牛国产精品| 人妻激情另类乱人伦人妻| 午夜精品久久99蜜桃的功能介绍| 三上悠亚免费在线观看| 综合天堂久久久久久久| 一本大道东京热无码aⅴ| 国内精品久久久久久久97牛牛 | 丁香亚洲综合激情啪啪综合| 亚洲精品鲁一鲁一区二区三区| 丁香五精品蜜臀久久久久99网站| 亚洲欧美高清在线| 99精品1区2区| 欧美精品日韩在线| 亚洲欧美视频在线观看视频| 国内偷拍精品视频| 五月婷婷综合网| 日本免费精品视频| 欧美日韩精品一区视频| 国产福利视频导航| 亚洲精品久久久久国产| 国产玉足榨精视频在线观看| 中文字幕在线观看日韩| 国产美女在线观看| 97精品一区二区三区| 625成人欧美午夜电影| 国产拍精品一二三| 精品一区二区三区免费看| 久久大片网站| 欧美成人激情| 国产一区二区视频播放| 日韩1区2区3区| 久久黄色一级视频| 91视频.com| 国产精品国产精品88| 亚洲va国产va欧美va观看| 最新中文字幕免费| 精品国产sm最大网站免费看| 巨骚激情综合| 久久亚洲精品视频| 一区二区精品伦理...| 国产在线精品成人一区二区三区| 久久人人爽人人爽人人片av不| 亚洲国产精品一区在线观看不卡| 欧美精品入口| 国产视频一区二区视频| 国产69精品久久777的优势| 在线观看免费黄色网址| 亚洲18色成人| 国产视频在线观看免费| 亚洲精品永久免费| 欧美1234区| 国产精品一区二区久久国产| 国产一区二区在线视频你懂的| 亚洲精蜜桃久在线| 国产婷婷精品| 精人妻一区二区三区| 中文字幕免费一区| 久久久久久久久久免费视频| 在线播放91灌醉迷j高跟美女 | 免费的黄色av| 日韩三级成人av网| se01亚洲视频| 久久久久久久久久码影片| 欧美91精品| 日韩va在线观看| 国产精品色在线| 国产免费av一区| 亚洲精品国产精品国自产在线| 看黄网站在线| 国产精品自拍小视频| 国内精品久久久久久久影视简单| 欧美大片在线播放| 成人一区在线看| 青娱乐国产在线| 欧美喷水一区二区| www在线播放| 国产精品成人一区二区| 久久97视频| 久久久久狠狠高潮亚洲精品| av中文一区二区三区| 国产在线观看免费av| 精品少妇一区二区三区日产乱码| 黄色网页在线观看| 成人xvideos免费视频| 成人激情在线| 一区二区在线播放视频| 91丨porny丨国产| av图片在线观看| 亚洲欧美日韩一区在线| 丝袜美腿诱惑一区二区三区| 久久久一本精品99久久精品| 91久久视频| 屁屁影院国产第一页| 婷婷中文字幕一区三区| 少妇人妻偷人精品一区二区| 久久久久久久电影一区| 嗯用力啊快一点好舒服小柔久久| www.九色.com| 97久久人人超碰| 少妇久久久久久久| 在线看日韩av| www欧美在线观看| 欧美交换配乱吟粗大25p| 粉嫩高潮美女一区二区三区| 免费一级特黄特色大片| 亚洲精品按摩视频| 亚洲wwww| 一本久久a久久精品vr综合| 国产综合色视频| 免费在线观看av网址| 亚洲精品久久久久久久久久久| 自拍在线观看| 亚洲国产欧美日韩| 狠狠狠色丁香婷婷综合激情| 欧美极品aaaaabbbbb| 亚洲精品美女久久久| 四虎4545www精品视频| 欧美aaa在线观看| 成人av电影免费在线播放| 国产无精乱码一区二区三区| 亚洲人成电影在线播放| 欧美成人家庭影院| 亚洲国产一二三精品无码 | 久久66热这里只有精品| 欧美一级久久| 国产一区二区三区视频播放| 这里只有精品99re| 成人免费图片免费观看| 日韩尤物视频| 精品一区二区三区的国产在线播放| 全网免费在线播放视频入口| 亚洲国产小视频| 欧美97人人模人人爽人人喊视频| www污在线观看| 国产亚洲欧洲997久久综合| 国产精品女人久久久| 久久久久久久影院| 日本一区二区免费高清| 中文字幕一二三区| 91久久一区二区| 欧洲成人综合网| 欧美日韩在线高清| 国产成人av电影在线观看| 色av性av丰满av| 欧美精品999| 国产高清一区二区| 蜜桃传媒一区二区亚洲av| 91精品国产综合久久精品性色| 中文字幕乱码在线播放|