必须配置fset、mode、src和错误检查,否则parser.ParseFile返回nil或位置错误;函数名在f.Name.Name,参数列表需判空;结构体注释在ast.GenDecl.Doc而非ast.TypeSpec.Doc。

直接用 ast.Inspect 配合类型断言就能拿到函数、结构体、变量等核心结构,但不设对 parser.Mode、不检查 err、不判空字段,一跑就 panic。
parser.ParseFile 调用前必须配齐这四样
漏掉任一,file 为 nil 或节点位置全错,后续遍历必崩:
-
fset必须是token.NewFileSet()创建的非 nil 值,否则所有node.Pos()返回 0 - 文件名参数可传空字符串
"",但若从磁盘读取,建议传绝对路径;若解析内存字符串(如os.ReadFile结果),它只是占位符,不校验存在性 -
mode不能为 nil:要注释就得加parser.ParseComments,要容忍语法错误继续解析就得加parser.AllErrors -
src决定读取方式:传nil表示从文件路径加载;传字符串则必须非 nil,否则解析器直接跳过
遍历函数声明时为什么拿不到 func main 或参数名
*ast.FuncDecl 字段命名和语义脱节,直接取容易 panic:
- 函数名在
f.Name.Name,不是f.Name—— 后者是*ast.Ident节点,未判空就取会崩 -
f.Type.Params和f.Type.Results可能为 nil(比如func hello() {}),不是空切片,必须先判空再访问.List - 每个参数是
*ast.Field,名字在field.Names([]*ast.Ident),匿名参数(如func(int))该切片为空,取[0]必 panic -
f.Doc是函数上方的注释,但仅当mode包含parser.ParseComments才非 nil
为什么优先用 ast.Inspect 而不是手写递归遍历 Decls
手写递归看似简单,实际漏节点严重,且易 panic:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
-
func() {}这类*ast.FuncLit不在f.Decls里,而是在表达式中 - 结构体字段定义藏在
*ast.StructType.Fields,不经过*ast.GenDecl就根本碰不到 -
switch分支里的fallthrough在*ast.CaseClause.Body中,不在顶层语句列表 -
ast.Inspect自动覆盖全部节点类型,包括*ast.FuncLit、*ast.CompositeLit、*ast.TypeSpec等冷门但高频结构 - 回调签名是
func(ast.Node) bool,返回false可立即中断(如只找第一个main函数)
提取结构体注释为什么 TypeSpec.Doc 总是空
结构体类型声明的注释不挂在 *ast.TypeSpec 上,而是挂在外层 *ast.GenDecl 上:
- 顶层
type T struct{}是一个*ast.GenDecl,其中Specs包含*ast.TypeSpec - 文档注释属于
*ast.GenDecl的Doc字段,不是TypeSpec.Doc - 所以得先断言
node.(*ast.GenDecl),再检查g.Doc != nil,然后遍历g.Specs找*ast.TypeSpec - 真要批量处理文档,建议直接用
go/doc包,它已封装好这套逻辑
最常被忽略的是:AST 是只读结构,ast.Inspect 回调里改任何字段都没用;真要重写代码,得换 golang.org/x/tools/go/ast/astutil 或手动构造新节点。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










