parser.parsefile参数错误会导致*ast.file为nil或panic,必须用token.newfileset()创建fset、传绝对路径、启用parser.parsecomments和allerrors模式,并严格检查err和f非nil。

parser.ParseFile 传参不对,AST 直接 nil 或 panic
直接调用 parser.ParseFile 却没传对参数,是最常见的硬伤。它不帮你兜底,文件不存在、路径错、编码非 UTF-8、语法错误——全都会让返回的 *ast.File 为 nil,而错误藏在 err 里。
必须做三件事:
-
fset一定提前用token.NewFileSet()创建,且不能复用给多个并发解析(FileSet非线程安全) - 第二个参数建议传绝对路径(用
filepath.Abs),传空字符串""虽合法,但错误位置显示成<standard input></standard>,调试困难 - 第四个参数
mode至少加parser.ParseComments,否则注释全丢;想收集所有语法问题,得加parser.AllErrors,不然遇到第一个错就停
别省略 if err != nil 检查——跳过这步,后面任何 file.Decls 访问都可能 panic。
遍历 FuncDecl 时,Type.Params 或 Results 为 nil 导致 panic
Go 允许无参函数(func hello() {})和无返回值函数(func do() {}),这时 funcDecl.Type.Params 和 funcDecl.Type.Results 就是 nil,不是空切片。直接写 for _, f := range f.Type.Params.List 必 panic。
正确做法永远先判空:
if f.Type.Params != nil { for _, field := range f.Type.Params.List { ... } }if f.Type.Results != nil { for _, field := range f.Type.Results.List { ... } }- 字段类型可能是
*ast.Ellipsis(比如...string),别当成*ast.ArrayType处理
注意 func init() 也是 *ast.FuncDecl,但 f.Name.Name == "init",没有导出名,别误当普通函数处理。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
用 ast.Inspect 找函数却漏掉闭包或嵌套定义
ast.Inspect 默认只遍历顶层声明(f.Decls),但 *ast.FuncLit(匿名函数字面量)藏在表达式里,比如 go func() {}() 或 var f = func() {},不会出现在 f.Decls 中。
如果目标是提取所有可调用函数体(包括闭包),得主动进表达式节点找:
- 在
ast.Inspect回调里,除了判*ast.FuncDecl,还要检查*ast.CallExpr的Fun字段是否为*ast.FuncLit -
*ast.FuncLit结构和*ast.FuncDecl类似,但没Name,只有Type和Body - 别指望靠
ast.Walk自动覆盖——它也不进CallExpr.Fun这种“非声明”位置,还是得手动钻
另外,ast.Inspect 不提供父节点信息,想区分“顶层函数”和“方法内定义的闭包”,得自己维护栈,记录当前所在作用域层级。
AST 解析完,下一步该用 go/types 补类型信息
go/ast 只管语法结构,不回答“这个 fmt.Println 是哪个包的”“a + b 能不能算”这类问题。它告诉你有个 *ast.CallExpr,但不告诉你调用的是哪个函数、参数类型是否匹配。
需要类型信息时,必须走 go/types 流程:
- 用
parser.ParseDir或parser.ParseFile得到*ast.Package - 构造
types.Config,调用Config.Check对包做类型检查,得到*types.Package - 通过
types.Info中的Types、Defs、Uses映射,把 AST 节点和具体类型/对象关联起来
比如想确认某个 *ast.Ident 是变量还是函数,或者它的实际类型是 int 还是 uint64,不走这一步,光看 AST 是没法确定的。很多代码生成工具卡在这儿——以为 AST 有全部信息,其实只是半成品。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










