Skip to content

📊 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 响应缓慢时长时间阻塞。
  • 📥 调用 Statisticsrepo.Statistics(ctx) 一次性返回 *domain.StatisticsResponse,其 Totals 字段聚合了 DownloadsPackagesVersions 三个核心总量。调用时务必检查 err,网络抖动或限流都可能让请求失败。
  • 🖨️ 展示原始总量:直接读取 stats.Totals.* 三个字段并格式化输出,这是仪表盘「概览卡片」最常用的数据源。
  • 🧮 计算衍生指标:在 Packages > 0 的保护下,用 Downloads / PackagesVersions / 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 方法

方法名所属包说明文档链接
Statisticspkg/repository获取 Packagist 仓库整体统计(下载量/包数/版本数)get-statistics
StatisticsResponse / Totalspkg/domain统计数据响应结构体与总量嵌套体statistics
Optionspkg/repository仓库客户端配置(ServerUrl 等)options

进阶

  • 📉 趋势记录:把每日拉取的 Totals 写入时序数据库(如 Prometheus / InfluxDB),绘制下载量增长曲线,量化生态扩张速度。
  • 🪞 镜像覆盖度评估:对比自建 Satis / 私有镜像的包总数与官方 Packages 总量,得到覆盖率指标,指导镜像同步策略。
  • 🔁 定时采集:用 cron 或 Kubernetes CronJob 每小时调用一次 Statistics,配合 context.WithTimeout 控制单次请求时长,失败时退避重试。
  • 🧱 单包统计扩展:在拿到仓库总量后,可进一步调用单包 PackageStats 接口,计算某包下载量占总量百分比,定位生态中的「头部包」。
  • 🌍 国际化数字:将 formatNumber 替换为 golang.org/x/x/text/messagemessage.NewPrinter(language.SimplifiedChinese),自动适配各地区千位/小数符号。
  • 📊 结构化输出:把 StatisticsResponse 序列化为 JSON 写入文件或推送到监控面板,供下游系统消费,而不仅限于终端打印。

基于 MIT 许可证发布