
go/doc 包不会将方法直接列在 `pkg.funcs` 中,而是将其归类到对应类型的 `methods` 字段下;需遍历 `pkg.types`,再访问每个 `type.methods` 才能完整获取所有导出与非导出方法的文档。
在使用 Go 标准库的 go/doc 包解析源码文档时,一个常见误区是认为所有可导出实体(包括函数和方法)都会统一出现在 pkg.Funcs 列表中。实际上,go/doc 严格遵循 Go 的类型系统语义:方法属于类型(如 struct、interface 或自定义类型)的成员,而非包级函数。因此,pkg.Funcs 仅包含包级函数(即无接收者或接收者为非本地定义类型的函数),而所有方法——无论是否导出、是否嵌入——均被组织在 pkg.Types[i].Methods 中。
以下是一个完整的示例,展示如何正确提取包内所有类型的方法文档:
pkg := doc.New(mainPkg, "./", doc.AllDecls)
// 遍历所有类型(struct、interface、type alias 等)
for _, typ := range pkg.Types {
log.Infof("Type: %s", typ.Name)
// 遍历该类型的所有方法(含嵌入类型的方法)
for _, method := range typ.Methods {
recv := ""
if method.Recv != nil {
recv = method.Recv.Type.String() // 如 "*MyStruct" 或 "MyStruct"
}
log.Infof(" Method: %s(%s) — %s", method.Name, recv,
strings.TrimSpace(strings.SplitN(method.Doc, "\n", 2)[0]))
}
}⚠️ 注意事项:
- doc.AllDecls 是必需的模式(而非默认的 doc.PackageOnly),否则类型及其方法可能被忽略;
- Type.Methods 已自动包含嵌入类型(anonymous fields)所带入的方法(即“提升的方法”),无需额外处理嵌入链;
- 方法的 Recv 字段为 *ast.Field 类型,其 Type 表示接收者类型;若需格式化显示,建议用 go/format.Node 或 ast.Print 辅助解析,但简单场景下 Recv.Type.String() 已足够;
- go/doc 不解析跨包方法(如 *bytes.Buffer.Write),仅处理当前包定义的类型及其方法。
总结:要完整提取 Go 包中的方法文档,核心逻辑是「先按类型聚合,再按方法展开」。跳过 pkg.Types 直接扫描 pkg.Funcs 将必然遗漏全部方法——这不是 bug,而是 go/doc 对 Go 语言语义的精准建模。










