Go 开发者对 pkg.go.dev 再熟悉不过——查文档、看版本、确认依赖可用性,几乎每天都在用。但一直以来,它只有网页界面,想批量获取包信息只能靠爬页面或者拼凑第三方数据。现在 Go 团队正式推出了 pkg.go.dev 的编程式 API,开发者可以直接请求包和模块的结构化数据,终于不用再自己写 HTML 解析了。
API 能拿到什么
新 API 返回的是 JSON 格式的包与模块元数据,核心字段包括:
- 模块路径、版本、发布时间
- 包的导入路径、所属模块
- 包的文档摘要、许可证信息
- 模块的依赖列表与 Go 版本要求
这些数据覆盖了 pkg.go.dev 网页上展示的大部分信息,但以结构化方式返回,方便工具链和自动化脚本消费。
接口地址与基本调用
API 的根路径为 https://pkg.go.dev/api/{path},目前支持的主要端点:
| 端点 | 说明 |
|---|---|
/api/packages/{import_path} |
查询指定包的元数据 |
/api/modules/{module_path} |
查询指定模块的元数据 |
/api/modules/{module_path}@{version} |
查询指定版本的模块信息 |
请求方式为标准 HTTP GET,返回 JSON。不需要认证,但有速率限制(官方建议合理使用,避免高频批量拉取)。
下面用 curl 直接试一下,查 github.com/gin-gonic/gin 这个包:
# 查询 gin 包的元数据
curl -s 'https://pkg.go.dev/api/packages/github.com/gin-gonic/gin' | jq .
返回的 JSON 大致结构如下(字段名以实际响应为准):
{
"ImportPath": "github.com/gin-gonic/gin",
"Module": {
"Path": "github.com/gin-gonic/gin",
"Version": "v1.9.1",
"Time": "2023-05-30T00:00:00Z"
},
"Synopsis": "Gin is a HTTP web framework written in Go...",
"Licenses": ["MIT"],
"GoVersion": "1.20"
}
用 jq 过滤出关键字段也很方便:
# 只看版本和许可证
curl -s 'https://pkg.go.dev/api/packages/github.com/gin-gonic/gin' \
| jq '{version: .Module.Version, license: .Licenses}'
在 Go 代码里集成
更常见的场景是在 Go 工具或 CI 流程中调用。下面是一个最小可运行的示例,拉取指定模块的最新版本信息:
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
// ModuleInfo 对应 API 返回的模块元数据结构
// 实际字段请参照 pkg.go.dev API 文档,此处为精简版
type ModuleInfo struct {
Path string `json:"Path"`
Version string `json:"Version"`
Time string `json:"Time"`
GoMod string `json:"GoMod"`
}
func fetchModuleInfo(modulePath string) (*ModuleInfo, error) {
url := "https://pkg.go.dev/api/modules/" + modulePath
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Get(url)
if err != nil {
return nil, fmt.Errorf("请求失败: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("非 200 状态码: %d", resp.StatusCode)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("读取响应体失败: %w", err)
}
var info ModuleInfo
if err := json.Unmarshal(body, &info); err != nil {
return nil, fmt.Errorf("解析 JSON 失败: %w", err)
}
return &info, nil
}
func main() {
info, err := fetchModuleInfo("github.com/gin-gonic/gin")
if err != nil {
fmt.Printf("错误: %v\n", err)
return
}
fmt.Printf("模块: %s\n最新版本: %s\n发布时间: %s\n",
info.Path, info.Version, info.Time)
}
运行方式:
go mod init example.com/pkggoapi
go run main.go
输出类似:
模块: github.com/gin-gonic/gin
最新版本: v1.9.1
发布时间: 2023-05-30T00:00:00Z
注意:上面的
ModuleInfo结构体是精简版。实际 API 返回的字段更多,建议先curl一次完整响应,再按需补充结构体字段。API 文档地址在 pkg.go.dev 页面底部可以找到。
实战场景:依赖许可证批量扫描
一个直接有用的场景——扫描项目所有直接依赖的许可证,避免引入合规风险。结合 go list 和 pkg.go.dev API 可以快速实现:
# 列出当前模块的所有直接依赖
go list -m -json all | jq -r '.Path' | while read mod; do
license=$(curl -s "https://pkg.go.dev/api/modules/$mod" | jq -r '.Licenses[0] // "未知"')
echo "$mod -> $license"
done
这段脚本逐个查询依赖模块的许可证,输出类似:
github.com/gin-gonic/gin -> MIT
github.com/go-sql-driver/mysql -> MPL-2.0
golang.org/x/text -> BSD-3-Clause
如果项目依赖多,建议加 sleep 0.5 控制请求频率,避免触发速率限制。
使用边界与注意事项
拿到 API 不等于可以无限制拉取,有几个实际约束需要留意:
- 速率限制:官方没有公布具体阈值,但明确要求不要高频批量请求。做全量扫描时务必加间隔,或考虑缓存结果。
- 数据新鲜度:API 返回的是 pkg.go.dev 已索引的数据。刚发布的新模块可能尚未入库,会有短暂延迟。
- 字段稳定性:这是首次公开的 API,字段结构可能随版本迭代调整。生产工具中建议做字段兼容处理,不要硬依赖所有键都存在。
- 仅限公开模块:私有模块不在 pkg.go.dev 的索引范围内,API 自然也无法返回。
什么时候该用
几个适合引入这个 API 的时机:
- CI 流程中检查依赖合规性——自动扫描许可证和版本。
- 内部工具展示依赖文档摘要——不用跳转到网页就能看到包的 Synopsis。
- 版本升级决策——批量对比依赖模块的最新版本与当前使用版本。
- 生成团队依赖报告——汇总模块路径、版本、许可证、Go 版本要求。
如果只是偶尔查一个包,直接打开 pkg.go.dev 网页更直观。API 的价值在于批量、自动化、可编程——把原本需要人眼扫页面的工作交给脚本。
pkg.go.dev API 的开放填补了 Go 生态里一个长期缺口:包元数据的结构化获取。从爬页面到调接口,工具链的可靠性会明显提升。建议先在小规模场景试用,等字段结构稳定后再铺开到关键流程。