Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the function of Ast in Go language

2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)05/31 Report--

This article introduces the relevant knowledge of "what is the role of Ast in Go language". In the operation of practical cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

What is ast? I have an excerpt from Wikipedia:

In computer science, abstract grammar tree (Abstract Syntax Tree,AST), or syntax tree for short (Syntax tree), is an abstract representation of the grammatical structure of source code. It represents the syntax structure of the programming language in the form of a tree, and each node on the tree represents a structure in the source code.

The core is that ast can represent the code structure in the form of a tree. With the tree structure, you can traverse it and do a lot of things.

Suppose a scene

Suppose a scenario: we can obtain various characteristics of the driver from an interface of the driver platform, such as age, number of orders, income, daily driving time, driving age, average speed, number of complaints. Data is generally transmitted by json.

The younger sister who runs the driver platform often needs to engage in some activities, such as selecting:

A veteran driver with more than 10000 orders and more than 5 years of driving experience

Efficient drivers who drive less than 3 hours a day and earn more than 500

A "wild" driver who is older than 40 and whose average speed is more than 70

……

These rules are not fixed and often change, but they are always a combination of driver characteristics.

To simplify, we select two features and use a Driver structure to represent them:

Type Driver struct {Orders int DrivingYears int}

In order to cooperate with the operation, we need to judge whether a driver meets the requirements according to the rules given by the operator.

If there are many people in the company, you can arrange a rd to wait on the operation sister, and modify the code manually every time you do an activity, which is not impossible. And it's actually quite simple, let's write a sample code:

/ / obtain driver characteristics from a third party Json means func getDriverRemote () [] byte {return [] byte (`{"orders": 100000, "driving_years": 18}`)} / / determine whether it is a veteran driver func isOldDriver (d * Driver) bool {if d.Orders > 10000 & & d.DrivingYears > 5 {return true} return false} func main () {bs: = getDriverRemote () var dDriver json.Unmarshal (bs, & d) fmt.Println (isOldDriver (& d)}

Look directly at the main function: getDriverRemote simulates to obtain the characteristic data of a driver from a third-party RPC, which is represented by json. Then json.Unmarshal deserializes the Driver structure. Finally, the isOldDriver function is called to determine whether the driver conforms to the operation rules.

IsOldDriver uses the if statement to determine whether the driver is a veteran driver based on the two fields of the Driver structure.

It's pretty simple.

But every time you update the rules, you have to go through a complete online process, which is also very troublesome. Is there an easier way? This allows us to directly parse a rule represented by a string given to us by the operation team, and directly return a value of type bool to indicate whether the condition is met.

Yes, there is!

Next is the core of this article, how to use ast to accomplish the same function.

Intuitively understand how to parse rules with ast

Using some of the functions provided by the ast package, we can easily change the following rule string:

Orders > 10000 & & driving_years > 5

Parse into a binary tree like this:

Regular binary tree

Where ast.BinaryExpr represents a binary expression, which consists of X and Y and the symbol OP. The top BinaryExpr indicates that the left and right half of the rule coincide.

Obviously, the left half is: orders > 10000, and the right half is: driving_years > 5. Miraculously, the left half and the right half happen to be a binary expression.

The orders > 10000 in the left half is actually the smallest leaf node, which can calculate a bool value. After taking it apart, it can be divided into X, Y and OP. X is "orders,OP" and Y is "10000". Where X represents an identifier, which is the ast.Ident type, and Y represents the literal quantity of a basic type, such as int type, string type... Is of type ast.BasicLit.

Driving_years > 18 in the right half can also be split according to this.

Then, take out the driver's orders field from json with a value of 100000, which is larger than 10000, so the left half is calculated as true. By the same token, the right half is calculated as true. Finally, counting the outermost "&", the result is still true.

At this point, we can calculate the result directly according to the rule string.

If written into a program, it is a dfs traversal process. If it is not a leaf node, then it is a binary expression node, then there must be X, Y, OP parts. Iterate through X recursively, and if X is a leaf node, end the recursion and calculate the value of X.

Here is another abstract syntax tree printed in the ast package:

Go print ast

In the figure above, 1, 2, 3 represent the outermost binary expression; 4, 5, and 6 represent the binary expression on the left.

Combined with this diagram, and then refer to the relevant structure code of the ast package, it is very clear. For example, the code of ast.BinaryExpr is as follows:

/ / A BinaryExpr node represents a binary expression. BinaryExpr struct {X Expr / / left operand OpPos token.Pos / / position of Op Op token.Token / / operator Y Expr / / right operand}

It has X, Y, OP, and even parses the location of the Op, represented by OpPos.

If you are still interested in the implementation, continue to look at the principle analysis section below, otherwise you can skip directly to the conclusion section.

Principle analysis

Using the above example, let's write an expression directly:

Orders > 10000 & & driving_years > 5

Then use ast to parse the rules and determine whether they are true or false.

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

For simplicity, we directly use map instead of json for the same reason, just for convenience.

The Eval function determines whether the rule is true or false:

/ / Eval: calculate the value of expr func Eval (m map [string] int64, expr string) (bool, error) {exprAst, err: = parser.ParseExpr (expr) if err! = nil {return false, err} / / print ast fset: = token.NewFileSet () ast.Print (fset, exprAst) return judge (exprAst, m), nil}

First parse the expression into Expr, and then call the judge function to evaluate the result:

/ / dfs func judge (bop ast.Node Mmap [int64] bool {/ / Leaf node if isLeaf (bop) {/ / asserts the binary expression expr: = bop. (* ast.BinaryExpr) x: = expr.X. (* ast.Ident) / / left y: = expr.Y. (* ast.BasicLit) / / right / / if it is the ">" symbol if expr.Op = = token.GTR {left: = m [x.Name] right _: = strconv.ParseInt (y.Value, 10,64) return left > right} return false} / / is not a leaf node, so it must be binary expression (we are only dealing with binary expressions currently) expr Ok: = bop. (* ast.BinaryExpr) if! ok {println ("this cannot be true") return false} / / Recursively calculate the values of the left and right nodes switch expr.Op {case token.LAND: return judge (expr.X, m) & & judge (expr.Y, m) case token.LOR: return judge (expr.X, m) | judge (expr.Y, m)} println ("unsupported operator") return false}

Judge uses dfs to recursively evaluate the expression.

The recursive termination condition is the leaf node:

/ / determine whether it is the smallest unit of a leaf node func isLeaf (bop ast.Node) bool {expr, ok: = bop. (* ast.BinaryExpr) if! ok {return false} / / binary expression. The left node is the identifier. The right node is the value _, okL: = expr.X. (* ast.Ident) _, okR: = expr.Y. (* ast.BasicLit) if okL & & okR {return true} return false} "what is the purpose of Ast in Go language". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report