当前位置: > > > > ast.Inspect 不走 *ast.UnaryExpr
来源:stackoverflow
2024-04-22 16:30:33
0浏览
收藏
哈喽!大家好,很高兴又见面了,我是的一名作者,今天由我给大家带来一篇《ast.Inspect 不走 *ast.UnaryExpr》,本文主要会讲到等等知识点,希望大家一起学习进步,也欢迎大家关注、点赞、收藏、转发! 下面就一起来看看吧!
问题内容
我正在尝试检查 go 源代码以制作一个工具。为此,我使用 ast.inspect
函数。
我需要知道函数/方法内部如何使用通道。
我将此作为要检查的示例代码:
package main func b(ch chan int) { for x := range ch { } }
这是函数 b 的 ast:
0 *ast.funcdecl { 1 . name: *ast.ident { 2 . . namepos: -:4:6 3 . . name: "b" 4 . . obj: *ast.object { 5 . . . kind: func 6 . . . name: "b" 7 . . . decl: *(obj @ 0) 8 . . } 9 . } 10 . type: *ast.functype { 11 . . func: -:4:1 12 . . params: *ast.fieldlist { 13 . . . opening: -:4:7 14 . . . list: []*ast.field (len = 1) { 15 . . . . 0: *ast.field { 16 . . . . . names: []*ast.ident (len = 1) { 17 . . . . . . 0: *ast.ident { 18 . . . . . . . namepos: -:4:8 19 . . . . . . . name: "ch" 20 . . . . . . . obj: *ast.object { 21 . . . . . . . . kind: var 22 . . . . . . . . name: "ch" 23 . . . . . . . . decl: *(obj @ 15) 24 . . . . . . . } 25 . . . . . . } 26 . . . . . } 27 . . . . . type: *ast.chantype { 28 . . . . . . begin: -:4:11 29 . . . . . . arrow: - 30 . . . . . . dir: 3 31 . . . . . . value: *ast.ident { 32 . . . . . . . namepos: -:4:16 33 . . . . . . . name: "int" 34 . . . . . . } 35 . . . . . } 36 . . . . } 37 . . . } 38 . . . closing: -:4:19 39 . . } 40 . } 41 . body: *ast.blockstmt { 42 . . lbrace: -:4:21 43 . . list: []ast.stmt (len = 1) { 44 . . . 0: *ast.rangestmt { 45 . . . . for: -:5:2 46 . . . . key: *ast.ident { 47 . . . . . namepos: -:5:6 48 . . . . . name: "x" 49 . . . . . obj: *ast.object { 50 . . . . . . kind: var 51 . . . . . . name: "x" 52 . . . . . . decl: *ast.assignstmt { 53 . . . . . . . lhs: []ast.expr (len = 1) { 54 . . . . . . . . 0: *(obj @ 46) 55 . . . . . . . } 56 . . . . . . . tokpos: -:5:8 57 . . . . . . . tok: := 58 . . . . . . . rhs: []ast.expr (len = 1) { 59 . . . . . . . . 0: *ast.unaryexpr { 60 . . . . . . . . . oppos: -:5:11 61 . . . . . . . . . op: range 62 . . . . . . . . . x: *ast.ident { 63 . . . . . . . . . . namepos: -:5:17 64 . . . . . . . . . . name: "ch" 65 . . . . . . . . . . obj: *(obj @ 20) 66 . . . . . . . . . } 67 . . . . . . . . } 68 . . . . . . . } 69 . . . . . . } 70 . . . . . } 71 . . . . } 72 . . . . tokpos: -:5:8 73 . . . . tok: := 74 . . . . x: *(obj @ 62) 75 . . . . body: *ast.blockstmt { 76 . . . . . lbrace: -:5:20 77 . . . . . rbrace: -:7:2 78 . . . . } 79 . . . } 80 . . } 81 . . rbrace: -:8:1 82 .
正如您在 59
行中看到的,我们可以看到有一个 unaryexpr
节点,其中 op
设置为 range
。这就是我想要捕获的节点。
我尝试使用此代码遍历 ast 并且仅捕获该节点。
exampleFunc := ` package main func B(ch chan int) { for x := range ch { } } ` fset := token.NewFileSet() file, err := parser.ParseFile(fset, "-", exampleFunc, parser.ParseComments) ast.Inspect(file, func(node ast.Node) bool { fn, ok := node.(*ast.UnaryExpr) // try to cast if !ok { return true } ast.Print(fset, fn) return true })
但似乎不起作用。
知道为什么,打印整个 funcdecl 的 ast,我可以看到有一个 unaryexpr 节点,但在尝试获取该节点时什么也没有出现?
解决方案
作为@mkopriva,*ast.Ident
节点被视为叶子。因此,我们需要手动从 RangeStmt
移动到 AssignStmt
(如果有的话),然后再次使用检查来到达 UnaryExpr
理论要掌握,实操不能落!以上关于《ast.Inspect 不走 *ast.UnaryExpr》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注公众号吧!