📊 get_statistics — 获取仓库统计数据
本示例演示如何调用 Packagist 仓库接口,一次性拿到总下载量、包数量与版本数量,并据此计算衍生指标。
示例定位
📚 这是一篇「远程数据读取 + 简单数据分析」的入门示例,定位如下:
- 🎯 学习目标:掌握通过
Repository客户端拉取仓库级统计数据的完整流程。 - 🔗 对应 SDK 方法:
repository.Repository.Statistics(ctx),返回domain.StatisticsResponse。 - 🧩 场景:在仪表盘上展示 Packagist 生态规模、记录每日总量变化趋势、评估自建镜像对官方仓库的覆盖度。
- 📈 延伸:示例还演示了如何基于原始总量计算「每包平均下载量」「每包平均版本数」等衍生指标,为后续做趋势分析打基础。
完整代码
go
package main
import (
"context"
"fmt"
"github.com/scagogogo/composer-skills/pkg/repository"
)
func main() {
// 步骤 1: 初始化仓库客户端
// 设置仓库选项,指向官方仓库
options := &repository.Options{
ServerUrl: "https://packagist.org",
}
// 创建仓库客户端
// 在真实代码中可能会有专门的构造函数
repo := &repository.Repository{}
// 仅为了避免未使用变量的警告
_ = options
// 步骤 2: 获取统计数据
fmt.Println("正在获取 Composer 仓库统计数据...")
// 创建上下文
ctx := context.Background()
// 调用 Statistics API 获取统计数据
stats, err := repo.Statistics(ctx)
if err != nil {
fmt.Printf("获取统计数据失败: %v\n", err)
return
}
// 步骤 3: 处理和显示统计数据
fmt.Println("\n仓库统计数据:")
fmt.Printf(" 总下载量: %d\n", stats.Totals.Downloads)
fmt.Printf(" 包数量: %d\n", stats.Totals.Packages)
fmt.Printf(" 版本数量: %d\n", stats.Totals.Versions)
// 步骤 4: 计算一些衍生指标(示例)
if stats.Totals.Packages > 0 {
// 计算每个包的平均下载量
avgDownloadsPerPackage := float64(stats.Totals.Downloads) / float64(stats.Totals.Packages)
fmt.Printf("\n每个包的平均下载量: %.2f\n", avgDownloadsPerPackage)
// 计算每个包的平均版本数
avgVersionsPerPackage := float64(stats.Totals.Versions) / float64(stats.Totals.Packages)
fmt.Printf("每个包的平均版本数: %.2f\n", avgVersionsPerPackage)
}
// 步骤 5: 格式化数据以便人类阅读(示例)
formattedDownloads := formatNumber(stats.Totals.Downloads)
fmt.Printf("\n格式化后的下载量: %s\n", formattedDownloads)
}
// formatNumber 格式化数字为易读形式,添加千位分隔符
func formatNumber(n int64) string {
str := fmt.Sprintf("%d", n)
result := ""
// 从右向左每三位添加一个逗号
for i, c := range str {
if i > 0 && (len(str)-i)%3 == 0 {
result += ","
}
result += string(c)
}
return result
}代码讲解
- ⚙️ 初始化仓库客户端:构造
repository.Options并把ServerUrl指向https://packagist.org,再用&repository.Repository{}创建客户端。生产代码建议使用专门的构造函数,以便注入 HTTP 超时、代理与重试策略。 - 🌐 创建上下文:使用
context.Background()作为请求根上下文。在长链路服务里,请改用带超时/取消的context.WithTimeout,避免在 Packagist 响应缓慢时长时间阻塞。 - 📥 调用 Statistics:
repo.Statistics(ctx)一次性返回*domain.StatisticsResponse,其Totals字段聚合了Downloads、Packages、Versions三个核心总量。调用时务必检查err,网络抖动或限流都可能让请求失败。 - 🖨️ 展示原始总量:直接读取
stats.Totals.*三个字段并格式化输出,这是仪表盘「概览卡片」最常用的数据源。 - 🧮 计算衍生指标:在
Packages > 0的保护下,用Downloads / Packages与Versions / Packages得到「每包平均下载量」「每包平均版本数」,用于横向对比生态健康度。 - ✍️ 数字人性化格式化:
formatNumber自行实现千位分隔符插入,便于人类阅读大数字(如25,000,000,000)。生产场景可替换为golang.org/x/text/message等国际化库,顺便支持本地化分组符号。 - 🛡️ 错误处理:拿到
err后打印并return,避免后续对stats解引用空指针。示例为简化省略了重试与日志,实际应用中建议加入退避重试与结构化日志。
运行方式
bash
# 进入示例目录
cd /home/cc11001100/github/scagogogo/composer-skills/examples/get_statistics
# 直接运行(会发起真实 API 调用,请避免频繁执行)
go run main.go⚠️ 注意:该示例会真实访问
https://packagist.org/statistics.json,请控制调用频率以免给目标服务器造成负担;网络受限环境下可在Options中配置代理。
涉及的 SDK 方法
| 方法名 | 所属包 | 说明 | 文档链接 |
|---|---|---|---|
Statistics | pkg/repository | 获取 Packagist 仓库整体统计(下载量/包数/版本数) | get-statistics |
StatisticsResponse / Totals | pkg/domain | 统计数据响应结构体与总量嵌套体 | statistics |
Options | pkg/repository | 仓库客户端配置(ServerUrl 等) | options |
进阶
- 📉 趋势记录:把每日拉取的
Totals写入时序数据库(如 Prometheus / InfluxDB),绘制下载量增长曲线,量化生态扩张速度。 - 🪞 镜像覆盖度评估:对比自建 Satis / 私有镜像的包总数与官方
Packages总量,得到覆盖率指标,指导镜像同步策略。 - 🔁 定时采集:用 cron 或 Kubernetes CronJob 每小时调用一次
Statistics,配合context.WithTimeout控制单次请求时长,失败时退避重试。 - 🧱 单包统计扩展:在拿到仓库总量后,可进一步调用单包
PackageStats接口,计算某包下载量占总量百分比,定位生态中的「头部包」。 - 🌍 国际化数字:将
formatNumber替换为golang.org/x/x/text/message的message.NewPrinter(language.SimplifiedChinese),自动适配各地区千位/小数符号。 - 📊 结构化输出:把
StatisticsResponse序列化为 JSON 写入文件或推送到监控面板,供下游系统消费,而不仅限于终端打印。