
使用 github api 列出用户所有仓库时,默认仅返回第一页结果;需手动分页遍历所有页面,才能完整获取全部公有及私有仓库。
使用 github api 列出用户所有仓库时,默认仅返回第一页结果;需手动分页遍历所有页面,才能完整获取全部公有及私有仓库。
GitHub REST API 对多数资源列表接口(如 /user/repos)实施分页限制,默认每页最多返回 30 条记录(可通过 per_page 参数调整,上限为 100),且不自动返回全部数据。即使已正确授权(scope=repo)并获得有效 OAuth token,若未显式处理分页,Go 客户端库 google/go-github 也只会返回首页结果,导致部分仓库(尤其是数量较多时)被遗漏。
在 Go 中,github.Repositories.List() 方法接受一个 github.ListOptions 结构体,其中包含 Page 和 PerPage 字段。要获取全部仓库,需循环调用该方法,每次递增 Page 值,直到某次响应的仓库切片长度小于 PerPage(表明已是最后一页):
import (
"context"
"fmt"
"log"
"github.com/google/go-github/v65/github"
"golang.org/x/oauth2"
)
func getAllRepositories(ctx context.Context, client *github.Client, token string) ([]*github.Repository, error) {
var allRepos []*github.Repository
opt := &github.RepositoryListOptions{
Type: "all", // 确保包含 public + private
PerPage: 100, // 最大允许值,减少请求数
}
page := 1
for {
repos, resp, err := client.Repositories.List(ctx, "", opt)
if err != nil {
return nil, fmt.Errorf("failed to list repos: %w", err)
}
allRepos = append(allRepos, repos...)
// 检查是否还有下一页
if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}
return allRepos, nil
}
// 使用示例(需提前配置带 repo scope 的 token)
func main() {
ctx := context.Background()
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: "your_personal_access_token"},
)
tc := oauth2.NewClient(ctx, ts)
client := github.NewClient(tc)
repos, err := getAllRepositories(ctx, client, "your_token")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Fetched %d repositories total\n", len(repos))
}⚠️ 注意事项:
- 权限必须完整:OAuth App 或 GitHub App 需请求 repo scope(而非仅 public_repo),否则私有仓库将被过滤;
- 速率限制:认证后默认 5000 次/小时,但大量仓库可能触发 API 限流,建议添加错误重试与 RateLimit 检查;
- 分页健壮性:推荐使用 resp.NextPage 字段而非手动递增 Page,因 API 可能跳过空页或返回非连续页码;
- 性能优化:PerPage=100 可显著减少请求数,但单次响应体积增大,需权衡网络与内存开销。
综上,完整获取用户全部仓库的关键在于主动实现分页迭代——这是 GitHub API 设计的通用模式,适用于 Issues、Pull Requests、Organizations 等几乎所有列表接口。


















