当前位置: 首页> 游戏> 网游 > golang AST语法树解析

golang AST语法树解析

时间:2025/7/14 0:59:50来源:https://blog.csdn.net/xidianhuihui/article/details/140449280 浏览次数:0次

1. 源码示例

package mainimport ("context"
)// Foo 结构体
type Foo struct {i int
}// Bar 接口
type Bar interface {Do(ctx context.Context) error
}// main方法
func main() {a := 1
}

2. Golang中的AST

golang官方提供的几个包,可以帮助我们进行AST分析:

  • go/scanner:词法解析,将源代码分割成一个个token

  • go/token:token类型及相关结构体定义

  • go/ast:ast的结构定义

    • ast的各种结构定义入口在go/ast/ast.go
  • go/parser:语法分析,读取token流生成ast

通过上述的四个库,我们就可以实现golang代码的语法树分析

3. 使用main.go解析demo.go的AST树

package mainimport ("go/ast""go/parser""go/token""log""path/filepath"
)func main() {fset := token.NewFileSet()// 这里取绝对路径,方便打印出来的语法树可以转跳到编辑器path, _ := filepath.Abs("./demo.go")f, err := parser.ParseFile(fset, path, nil, parser.AllErrors)if err != nil {log.Println(err)return}// 打印语法树ast.Print(fset, f)
}

3.1. 解析的结果如下

可在http://goast.yuroyoro.net/里贴上源代码后查看

*ast.File {1  .  Package: 1:12  .  Name: *ast.Ident {3  .  .  NamePos: 1:94  .  .  Name: "main"5  .  }6  .  Decls: []ast.Decl (len = 4) {7  .  .  0: *ast.GenDecl {8  .  .  .  TokPos: 3:19  .  .  .  Tok: import10  .  .  .  Lparen: 3:811  .  .  .  Specs: []ast.Spec (len = 1) {12  .  .  .  .  0: *ast.ImportSpec {13  .  .  .  .  .  Path: *ast.BasicLit {14  .  .  .  .  .  .  ValuePos: 4:215  .  .  .  .  .  .  Kind: STRING16  .  .  .  .  .  .  Value: "\"context\""17  .  .  .  .  .  }18  .  .  .  .  .  EndPos: -19  .  .  .  .  }20  .  .  .  }21  .  .  .  Rparen: 5:122  .  .  }23  .  .  1: *ast.GenDecl {24  .  .  .  TokPos: 8:125  .  .  .  Tok: type26  .  .  .  Lparen: -27  .  .  .  Specs: []ast.Spec (len = 1) {28  .  .  .  .  0: *ast.TypeSpec {29  .  .  .  .  .  Name: *ast.Ident {30  .  .  .  .  .  .  NamePos: 8:631  .  .  .  .  .  .  Name: "Foo"32  .  .  .  .  .  .  Obj: *ast.Object {33  .  .  .  .  .  .  .  Kind: type34  .  .  .  .  .  .  .  Name: "Foo"35  .  .  .  .  .  .  .  Decl: *(obj @ 28)36  .  .  .  .  .  .  }37  .  .  .  .  .  }38  .  .  .  .  .  Type: *ast.StructType {39  .  .  .  .  .  .  Struct: 8:1040  .  .  .  .  .  .  Fields: *ast.FieldList {41  .  .  .  .  .  .  .  Opening: 8:1742  .  .  .  .  .  .  .  List: []*ast.Field (len = 1) {43  .  .  .  .  .  .  .  .  0: *ast.Field {44  .  .  .  .  .  .  .  .  .  Names: []*ast.Ident (len = 1) {45  .  .  .  .  .  .  .  .  .  .  0: *ast.Ident {46  .  .  .  .  .  .  .  .  .  .  .  NamePos: 9:247  .  .  .  .  .  .  .  .  .  .  .  Name: "i"48  .  .  .  .  .  .  .  .  .  .  .  Obj: *ast.Object {49  .  .  .  .  .  .  .  .  .  .  .  .  Kind: var50  .  .  .  .  .  .  .  .  .  .  .  .  Name: "i"51  .  .  .  .  .  .  .  .  .  .  .  .  Decl: *(obj @ 43)52  .  .  .  .  .  .  .  .  .  .  .  }53  .  .  .  .  .  .  .  .  .  .  }54  .  .  .  .  .  .  .  .  .  }55  .  .  .  .  .  .  .  .  .  Type: *ast.Ident {56  .  .  .  .  .  .  .  .  .  .  NamePos: 9:457  .  .  .  .  .  .  .  .  .  .  Name: "int"58  .  .  .  .  .  .  .  .  .  }59  .  .  .  .  .  .  .  .  }60  .  .  .  .  .  .  .  }61  .  .  .  .  .  .  .  Closing: 10:162  .  .  .  .  .  .  }63  .  .  .  .  .  .  Incomplete: false64  .  .  .  .  .  }65  .  .  .  .  }66  .  .  .  }67  .  .  .  Rparen: -68  .  .  }69  .  .  2: *ast.GenDecl {70  .  .  .  TokPos: 13:171  .  .  .  Tok: type72  .  .  .  Lparen: -73  .  .  .  Specs: []ast.Spec (len = 1) {74  .  .  .  .  0: *ast.TypeSpec {75  .  .  .  .  .  Name: *ast.Ident {76  .  .  .  .  .  .  NamePos: 13:677  .  .  .  .  .  .  Name: "Bar"78  .  .  .  .  .  .  Obj: *ast.Object {79  .  .  .  .  .  .  .  Kind: type80  .  .  .  .  .  .  .  Name: "Bar"81  .  .  .  .  .  .  .  Decl: *(obj @ 74)82  .  .  .  .  .  .  }83  .  .  .  .  .  }84  .  .  .  .  .  Type: *ast.InterfaceType {85  .  .  .  .  .  .  Interface: 13:1086  .  .  .  .  .  .  Methods: *ast.FieldList {87  .  .  .  .  .  .  .  Opening: 13:2088  .  .  .  .  .  .  .  List: []*ast.Field (len = 1) {89  .  .  .  .  .  .  .  .  0: *ast.Field {90  .  .  .  .  .  .  .  .  .  Names: []*ast.Ident (len = 1) {91  .  .  .  .  .  .  .  .  .  .  0: *ast.Ident {92  .  .  .  .  .  .  .  .  .  .  .  NamePos: 14:293  .  .  .  .  .  .  .  .  .  .  .  Name: "Do"94  .  .  .  .  .  .  .  .  .  .  .  Obj: *ast.Object {95  .  .  .  .  .  .  .  .  .  .  .  .  Kind: func96  .  .  .  .  .  .  .  .  .  .  .  .  Name: "Do"97  .  .  .  .  .  .  .  .  .  .  .  .  Decl: *(obj @ 89)98  .  .  .  .  .  .  .  .  .  .  .  }99  .  .  .  .  .  .  .  .  .  .  }100  .  .  .  .  .  .  .  .  .  }101  .  .  .  .  .  .  .  .  .  Type: *ast.FuncType {102  .  .  .  .  .  .  .  .  .  .  Func: -103  .  .  .  .  .  .  .  .  .  .  Params: *ast.FieldList {104  .  .  .  .  .  .  .  .  .  .  .  Opening: 14:4105  .  .  .  .  .  .  .  .  .  .  .  List: []*ast.Field (len = 1) {106  .  .  .  .  .  .  .  .  .  .  .  .  0: *ast.Field {107  .  .  .  .  .  .  .  .  .  .  .  .  .  Names: []*ast.Ident (len = 1) {108  .  .  .  .  .  .  .  .  .  .  .  .  .  .  0: *ast.Ident {109  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  NamePos: 14:5110  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Name: "ctx"111  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Obj: *ast.Object {112  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Kind: var113  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Name: "ctx"114  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Decl: *(obj @ 106)115  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  }116  .  .  .  .  .  .  .  .  .  .  .  .  .  .  }117  .  .  .  .  .  .  .  .  .  .  .  .  .  }118  .  .  .  .  .  .  .  .  .  .  .  .  .  Type: *ast.SelectorExpr {119  .  .  .  .  .  .  .  .  .  .  .  .  .  .  X: *ast.Ident {120  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  NamePos: 14:9121  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Name: "context"122  .  .  .  .  .  .  .  .  .  .  .  .  .  .  }123  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Sel: *ast.Ident {124  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  NamePos: 14:17125  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Name: "Context"126  .  .  .  .  .  .  .  .  .  .  .  .  .  .  }127  .  .  .  .  .  .  .  .  .  .  .  .  .  }128  .  .  .  .  .  .  .  .  .  .  .  .  }129  .  .  .  .  .  .  .  .  .  .  .  }130  .  .  .  .  .  .  .  .  .  .  .  Closing: 14:24131  .  .  .  .  .  .  .  .  .  .  }132  .  .  .  .  .  .  .  .  .  .  Results: *ast.FieldList {133  .  .  .  .  .  .  .  .  .  .  .  Opening: -134  .  .  .  .  .  .  .  .  .  .  .  List: []*ast.Field (len = 1) {135  .  .  .  .  .  .  .  .  .  .  .  .  0: *ast.Field {136  .  .  .  .  .  .  .  .  .  .  .  .  .  Type: *ast.Ident {137  .  .  .  .  .  .  .  .  .  .  .  .  .  .  NamePos: 14:26138  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Name: "error"139  .  .  .  .  .  .  .  .  .  .  .  .  .  }140  .  .  .  .  .  .  .  .  .  .  .  .  }141  .  .  .  .  .  .  .  .  .  .  .  }142  .  .  .  .  .  .  .  .  .  .  .  Closing: -143  .  .  .  .  .  .  .  .  .  .  }144  .  .  .  .  .  .  .  .  .  }145  .  .  .  .  .  .  .  .  }146  .  .  .  .  .  .  .  }147  .  .  .  .  .  .  .  Closing: 15:1148  .  .  .  .  .  .  }149  .  .  .  .  .  .  Incomplete: false150  .  .  .  .  .  }151  .  .  .  .  }152  .  .  .  }153  .  .  .  Rparen: -154  .  .  }155  .  .  3: *ast.FuncDecl {156  .  .  .  Name: *ast.Ident {157  .  .  .  .  NamePos: 18:6158  .  .  .  .  Name: "main"159  .  .  .  .  Obj: *ast.Object {160  .  .  .  .  .  Kind: func161  .  .  .  .  .  Name: "main"162  .  .  .  .  .  Decl: *(obj @ 155)163  .  .  .  .  }164  .  .  .  }165  .  .  .  Type: *ast.FuncType {166  .  .  .  .  Func: 18:1167  .  .  .  .  Params: *ast.FieldList {168  .  .  .  .  .  Opening: 18:10169  .  .  .  .  .  Closing: 18:11170  .  .  .  .  }171  .  .  .  }172  .  .  .  Body: *ast.BlockStmt {173  .  .  .  .  Lbrace: 18:13174  .  .  .  .  List: []ast.Stmt (len = 1) {175  .  .  .  .  .  0: *ast.AssignStmt {176  .  .  .  .  .  .  Lhs: []ast.Expr (len = 1) {177  .  .  .  .  .  .  .  0: *ast.Ident {178  .  .  .  .  .  .  .  .  NamePos: 19:2179  .  .  .  .  .  .  .  .  Name: "a"180  .  .  .  .  .  .  .  .  Obj: *ast.Object {181  .  .  .  .  .  .  .  .  .  Kind: var182  .  .  .  .  .  .  .  .  .  Name: "a"183  .  .  .  .  .  .  .  .  .  Decl: *(obj @ 175)184  .  .  .  .  .  .  .  .  }185  .  .  .  .  .  .  .  }186  .  .  .  .  .  .  }187  .  .  .  .  .  .  TokPos: 19:4188  .  .  .  .  .  .  Tok: :=189  .  .  .  .  .  .  Rhs: []ast.Expr (len = 1) {190  .  .  .  .  .  .  .  0: *ast.BasicLit {191  .  .  .  .  .  .  .  .  ValuePos: 19:7192  .  .  .  .  .  .  .  .  Kind: INT193  .  .  .  .  .  .  .  .  Value: "1"194  .  .  .  .  .  .  .  }195  .  .  .  .  .  .  }196  .  .  .  .  .  }197  .  .  .  .  }198  .  .  .  .  Rbrace: 20:1199  .  .  .  }200  .  .  }201  .  }202  .  Scope: *ast.Scope {203  .  .  Objects: map[string]*ast.Object (len = 3) {204  .  .  .  "Foo": *(obj @ 32)205  .  .  .  "Bar": *(obj @ 78)206  .  .  .  "main": *(obj @ 159)207  .  .  }208  .  }209  .  Imports: []*ast.ImportSpec (len = 1) {210  .  .  0: *(obj @ 12)211  .  }212  .  Unresolved: []*ast.Ident (len = 3) {213  .  .  0: *(obj @ 55)214  .  .  1: *(obj @ 119)215  .  .  2: *(obj @ 136)216  .  }217  }

4. AST树结构

// 该结构体位于标准包 go/ast/ast.go 中,有兴趣可以转跳到源码阅读更详尽的注释
type File struct {Doc        *CommentGroup   // 如果文件有文档,则文档会被存储在这个结构体中,否则为 nilPackage    token.Pos       // "package"关键字,主要是所在的位置信息Name       *Ident          // package的名字Decls      []Decl          // 文件级别的声明。它包含文件中所有变量、函数、类型声明。如果文件中没有声明,则 decls 值为 nilScope      *Scope          // 包级作用域。它代表包级作用域,包含所有在包内声明的变量和函数。它对当前文件有效Imports    []*ImportSpec   // imports in this fileUnresolved []*Ident        // unresolved identifiers in this file。未使用的标识符Comments   []*CommentGroup // 文件中的所有注释。它包含文件中所有注释的列表
}

img

img

4.1. Doc

如果文件有文档,则文档会被存储在这个结构体中,否则为 nil

todo:目前没找到什么样的源代码解析成AST树后有Doc的

4.2. Package

*ast.File {1  .  Package: 1:12  .  Name: *ast.Ident {3  .  .  NamePos: 1:94  .  .  Name: "main"5  .  }

Package: 1:1, package关键字所在的位置

4.3. Name

img

type为ast.ident,表示它是一个变量值,可以看到内容为"main"

4.4. Decls

文件级别的声明。它包含文件中所有变量、函数、类型声明。如果文件中没有声明,则 decls 值为 nil

img

4.5. Decls总共有三种类型

img

4.5.1. BadDecl

语法出错的声明

4.5.2. GenDecl

常规的声明,包含以下部分

  • import
  • constant
  • type
  • variable
4.5.2.1. import

img

4.5.2.2. constant
4.5.2.3. type

img

4.5.2.4. variable

4.5.3. FunDecl

方法的声明

4.6. Scope

包级作用域。它代表包级作用域,包含所有在包内声明的变量和函数。它对当前文件有效

img

4.6.1. 示例如下

img

4.7. Imports

回顾以下File结构体定义,其中ImportsImportSpec类型数组

// 该结构体位于标准包 go/ast/ast.go 中,有兴趣可以转跳到源码阅读更详尽的注释
type File struct {Doc        *CommentGroup   // 如果文件有文档,则文档会被存储在这个结构体中,否则为 nilPackage    token.Pos       // "package"关键字,主要是所在的位置信息Name       *Ident          // package的名字Decls      []Decl          // 文件级别的声明。它包含文件中所有变量、函数、类型声明。如果文件中没有声明,则 decls 值为 nilScope      *Scope          // 包级作用域。它代表包级作用域,包含所有在包内声明的变量和函数。它对当前文件有效Imports    []*ImportSpec   // imports in this fileUnresolved []*Ident        // unresolved identifiers in this file。未使用的标识符Comments   []*CommentGroup // 文件中的所有注释。它包含文件中所有注释的列表
}

ImportSpec结构体定义如下,一条import就是一个ImportSpec

// An ImportSpec node represents a single package import.ImportSpec struct {Doc     *CommentGroup // associated documentation; or nilName    *Ident        // local package name (including "."); or nilPath    *BasicLit     // import pathComment *CommentGroup // line comments; or nilEndPos  token.Pos     // end of spec (overrides Path.Pos if nonzero)}

img

4.8. Unresolved

unresolved identifiers in this file。未使用的标识符

4.9. Comments

文件中的所有注释。它包含文件中所有注释的列表。实际上这块有问题,并没有注释解析出来

5. AST数节点类型

6. 参考资料

  1. Golang AST语法树使用教程及示例
  2. GoAst Viewer
  3. https://github.com/DrmagicE/ast-example
  4. [golang深入源代码系列之一:AST的遍历](
关键字:golang AST语法树解析

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: