调用parser.ParseFile前必须检查四件事:fset非nil(用token.NewFileSet创建)、文件名合理(磁盘读取建议绝对路径,内存解析可为空字符串)、mode正确(如ParseComments)、src合法(nil表示磁盘读取,非nil字符串需非空);漏任一环节易致file为nil或panic。

parser.ParseFile调用前必须检查四件事
几乎所有 panic 都源于 parser.ParseFile 调用前上下文没配齐。漏掉任一环节,返回的 *ast.File 就是 nil,后续所有操作都崩。
-
fset必须是非 nil 的token.FileSet(用token.NewFileSet()创建),否则所有node.Pos()返回 0,定位失效 - 第二个参数(文件名)传空字符串
""可以,但若走磁盘读取,建议传绝对路径;若走内存解析(src非 nil),它只是占位符,不校验存在性 - 第四个参数
mode不能为 nil:要注释就加parser.ParseComments,要容忍语法错误继续解析就加parser.AllErrors -
src决定读取方式:传nil表示从文件路径加载;传字符串(如os.ReadFile结果)则必须非 nil,否则解析器直接跳过
典型 panic:panic: interface conversion: ast.Node is nil, not *ast.FuncDecl,基本等于你没检查 err != nil 就直接访问了 file。
ast.Inspect 是遍历首选,但类型断言必须带 ok 判断
ast.Inspect 比手写递归稳得多,它自动覆盖全部节点类型(包括 *ast.FuncLit、*ast.StructType、*ast.TypeSpec 等冷门但高频结构),还支持中途返回 false 中断遍历。但它不是万能的——用错就静默跳过或 panic。
- 回调签名是
func(node ast.Node) bool,类型断言必须带ok判断:if f, ok := node.(*ast.FuncDecl); ok { ... },否则遇到*ast.FuncLit(闭包)会静默跳过 - 别在回调里改
node字段——AST 是只读结构,改了无效,还可能干扰后续遍历 - 需要父节点或作用域信息?
ast.Inspect不提供,得自己维护栈;真要改 AST,得用golang.org/x/tools/go/ast/astutil - 别对
node做指针比较(比如node == someNode),AST 节点没实现==,恒为false
FuncDecl 字段访问前必须判空
*ast.FuncDecl 的字段命名和语义脱节,直接取容易 panic。Go 允许无参数、无返回值函数,所以很多字段是 nil,不是空切片。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
- 函数名在
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;f.Comments是整个文件注释列表,不是函数专属
想拿类型信息?go/ast 本身不提供,得接 go/types
go/ast 只管“长什么样”,不管“是什么类型”。比如 textToContain := bytes.NewBuffer(nil),*ast.Ident 节点里只有名字和位置,没有 *bytes.Buffer 这个类型。
- 要跨包解析(如
example_package.BaseObject)、推导字段类型、查方法集,必须引入go/types -
go/types能自动解析导入路径、构建类型环境(types.Info),把*ast.Ident映射到真实类型(types.Type)和对象(types.Object) - 单文件分析用
go/ast够了;但只要涉及符号绑定、接口实现判定、结构体字段类型推导,就必须上go/types+go/packages
最常被忽略的一点:go/ast 解析出来的每个节点,都是语法层面的“壳”;真正让分析有语义的,永远是 go/types 填进去的“肉”。没连上它,所有“类型推导”“跨包引用”“方法查找”都是空中楼阁。

















