ast.Inspect 可轻量提取函数声明信息:识别 *ast.FuncDecl 节点,通过 Name.Name 获取函数名,Type.Params 和 Type.Results 提取参数与返回值类型,Recv 安全获取接收者;需配合 go/types 补足语义信息。

如何用 ast.Inspect 提取函数声明的基本信息
直接遍历 AST 节点是获取函数名、参数、返回值最轻量的方式,ast.Inspect 比手动递归 ast.Walk 更简洁,也更符合常见调试/分析场景。
关键在于识别 *ast.FuncDecl 节点,并安全访问其字段——FuncDecl.Name 是标识符,不是字符串;FuncDecl.Type 才包含参数和结果签名。
-
FuncDecl.Name.Name是函数名(如"main"),若为nil表示是函数字面量,跳过 -
FuncDecl.Type.Params和FuncDecl.Type.Results是*ast.FieldList,需遍历其List字段提取每个参数/返回值的类型描述 - 别直接读
Params.List[0].Type—— 它可能是*ast.Ident(如int)、*ast.StarExpr(如*os.File)或*ast.SelectorExpr(如http.HandlerFunc),需用ast.Print或自定义typeString函数格式化
为什么 ast.ParseFile 会 panic 或返回空节点
常见原因是源文件路径错误、语法不合法,或未传入正确的 mode 参数。默认模式下,ast.ParseFile 不解析函数体(只保留 FuncDecl.Body == nil),但若你后续依赖 Body 做逻辑(比如统计行数、找 return 语句),就会出问题。
- 确保路径存在且可读,用
os.ReadFile先验证内容是否为空或含 BOM - 若需完整函数体,必须传
parser.AllErrors | parser.ParseComments,否则Body永远为nil - 遇到
syntax error: unexpected semicolon or newline,大概率是 Go 版本与 parser 不匹配(如用 Go 1.22 的语法在旧版go/parser下解析)
如何安全获取函数的接收者类型(receiver)
FuncDecl.Recv 是个 *ast.FieldList,长度最多为 1,但它可能为 nil(非方法)、为空列表(非法写法),或含一个带名字和类型的字段。直接取 Recv.List[0] 会 panic。
在 Golang 中使用 samber/hot 进行内存缓存,支持 LRU、LFU、TinyLFU、W‑TinyLFU、S3FIFO、ARC、TwoQueue、SIEVE、FIFO 等淘汰算法,提供 TTL、缓存加载器及分片功能。
立即学习“go语言免费学习笔记(深入)”;
- 先判空:
if decl.Recv != nil && len(decl.Recv.List) > 0 -
Recv.List[0].Names是接收者名字(如["r"]),可能为空切片(匿名接收者) -
Recv.List[0].Type才是真正类型,常见为*ast.StarExpr(指针接收者)或*ast.Ident(值接收者),需递归展开才能得到底层类型名(如*T→T) - 注意:嵌套结构体字段、泛型类型(
T[U])无法仅靠ast包还原完整类型名,此时应配合types.Info使用
用 go/types 补足 ast 无法提供的语义信息
ast 只做语法树解析,不校验类型、不展开别名、不处理泛型实例化。比如 type MyInt int 在 AST 中仍是 Ident,但你可能需要知道它底层是 int;又比如 func F[T any](x T) 的 T 在 AST 中只是标识符,无约束信息。
- 必须用
types.NewPackage+types.Config.Check构建类型检查器,再通过info.Defs或info.Types查对应节点的类型对象 -
ast.Inspect遍历时,把node.Pos()作为 key 去查info.Types,能拿到精确的类型(包括方法集、底层类型、泛型参数绑定) - 代价是启动慢、内存高,纯 AST 分析够用时,别盲目上
go/types
真正难的不是遍历节点,而是判断哪些字段该深挖、哪些该忽略,以及什么时候必须切换到类型系统。AST 是骨架,没类型信息,很多“函数信息”本质上是猜的。

















