赞
踩
在Go语言中,AST(Abstract Syntax Tree)即抽象语法树。它是一种用于表示源代码结构的数据结构,通过对源代码的语法分析,可以生成一棵AST,用于表示源代码的语法结构。
在Go语言中,AST是通过Go语言的内置包go/ast
来实现的。该包提供了一系列类型和函数,可以用于生成和操作AST。
例如,下面是一段Go语言源代码:
package main
import "fmt"
func main() {
fmt.Println("Hello, world!")
}
我们可以通过go/ast
包中的函数来生成这段代码的AST。
例如,可以使用parser.ParseFile
函数来解析一个源文件,并返回该文件的AST:
package main import ( "fmt" "go/ast" "go/parser" "go/token" ) func main() { // 解析源文件 fset := token.NewFileSet() f, err := parser.ParseFile(fset, "example.go", nil, 0) if err != nil { panic(err) } // 遍历AST ast.Inspect(f, func(n ast.Node) bool { // 处理节点 fmt.Println(n) return true }) }
局部输出
&{<nil> 1 main [0xc0000a20c0 0xc000092420] scope 0xc000010400 {
func main
}
[0xc000092210 0xc000092240 0xc000092270 0xc0000922a0] [token parser nil nil panic ast ast bool fmt true] []}
main
<nil>
&{<nil> 15 import 22 [0xc000092210 0xc000092240 0xc000092270 0xc0000922a0] 78}
&{<nil> <nil> 0xc0000aa020 <nil> 0}
&{28 STRING "fmt"}
上面的代码中,我们使用了parser.ParseFile
函数来解析一个源文件,并返回该文件的AST。然后,我们使用ast.Inspect
函数来遍历AST,并处理每个AST节点。在这个例子中,我们打印了每个节点的信息。
通过生成AST,我们可以对源代码的语法结构进行分析和操作。例如,可以通过遍历AST来寻找特定的节点,从而实现代码的查找、替换和重构等功能。
// package ast package ast /* the name is ast */ import "fmt" // StcA结构体说明 // descrpiton StcA type StcA struct { FA string `json:"fa" form:"fa"` //测试字段A Fb string `json:"fb" form:"fb"` } type StcB struct { A, B, C int // associated with a, b, c // associated with x, y x, y float64 // float values z complex128 // complex value }
package main import ( "fmt" "go/ast" "go/parser" "go/token" "io/ioutil" "strings" "testing" ) func main() { src, _ := ioutil.ReadFile("src.go") f := token.NewFileSet() p, err := parser.ParseFile(f, "src.go", src, parser.ParseComments) if err != nil { t.Fatal(err) } for _, v := range p.Decls { var ( structComment string structName string fieldNumber int ) if stc, ok := v.(*ast.GenDecl); ok && stc.Tok == token.TYPE { //fmt.Println(stc.Tok) //import、type、struct... if stc.Doc != nil { structComment = strings.TrimRight(stc.Doc.Text(), "\n") } for _, spec := range stc.Specs { if tp, ok := spec.(*ast.TypeSpec); ok { structName = tp.Name.Name fmt.Println("结构体名称:", structName) fmt.Println("结构体注释:", structComment) if stp, ok := tp.Type.(*ast.StructType); ok { if !stp.Struct.IsValid() { continue } fieldNumber = stp.Fields.NumFields() fmt.Println("字段数:", fieldNumber) for _, field := range stp.Fields.List { var ( fieldName string fieldType string fieldTag string fieldTagKind string fieldComment string ) //获取字段名 if len(field.Names) == 1 { fieldName = field.Names[0].Name //等同于field.Names[0].String()) //获取名称方法2 } else if len(field.Names) > 1 { for _, name := range field.Names { fieldName = fieldName + name.String() + "," } } if field.Tag != nil { fieldTag = field.Tag.Value fieldTagKind = field.Tag.Kind.String() } if field.Comment != nil { fieldComment = strings.TrimRight(field.Comment.Text(), "\n") } if ft, ok := field.Type.(*ast.Ident); ok { fieldType = ft.Name } fmt.Println("\t字段名:", fieldName) fmt.Println("\t字段类型:", fieldType) fmt.Println("\t标签:", fieldTag, "标签类型", fieldTagKind) fmt.Println("\t字段注释:", fieldComment) fmt.Println("\t----------") } } } } } } }
输出:
结构体名称: StcA 结构体注释: StcA结构体说明 descrpiton StcA 字段数: 2 字段名: FA 字段类型: string 标签: `json:"fa" form:"fa"` 标签类型 STRING 字段注释: 测试字段A ---------- 字段名: Fb 字段类型: string 标签: `json:"fb" form:"fb"` 标签类型 STRING 字段注释: ---------- 结构体名称: StcB 结构体注释: 字段数: 6 字段名: A,B,C, 字段类型: int 标签: 标签类型 字段注释: associated with a, b, c ---------- 字段名: x,y, 字段类型: float64 标签: 标签类型 字段注释: float values ---------- 字段名: z 字段类型: complex128 标签: 标签类型 字段注释: complex value ----------
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。