You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Go的HTTP请求中获取Links字段?附Python参考代码

在Go中实现GitHub仓库提交数统计(对应Python requests.links功能)

问题背景

你提供的Python代码通过requests.links自动解析GitHub API响应的Link头,从rel="last"的链接中提取page参数来计算仓库总提交数。在Go中,标准库的http.Response没有直接封装好的类似links的结构,需要手动解析Link头字段。

Go实现代码

package main

import (
	"fmt"
	"net/http"
	"net/url"
	"strings"
)

func getCommitsCount(owner, repo string) (int, error) {
	apiURL := fmt.Sprintf("https://api.github.com/repos/%s/%s/commits?per_page=1", owner, repo)

	resp, err := http.Get(apiURL)
	if err != nil {
		return 0, err
	}
	defer resp.Body.Close()

	// 获取Link响应头
	linkHeader := resp.Header.Get("Link")
	if linkHeader == "" {
		// 如果没有Link头,说明只有1页或0提交
		if resp.StatusCode == http.StatusOK {
			return 1, nil
		}
		return 0, fmt.Errorf("failed to get link header")
	}

	// 解析Link头,找到rel="last"的链接
	lastURL, err := parseLinkHeader(linkHeader, "last")
	if err != nil {
		return 0, err
	}

	// 解析URL中的page参数
	u, err := url.Parse(lastURL)
	if err != nil {
		return 0, err
	}
	pageStr := u.Query().Get("page")
	if pageStr == "" {
		return 0, fmt.Errorf("page parameter not found in last link")
	}

	// 转换为整数
	var commitCount int
	_, err = fmt.Sscanf(pageStr, "%d", &commitCount)
	if err != nil {
		return 0, err
	}

	return commitCount, nil
}

// parseLinkHeader 解析Link头,返回指定rel对应的URL
func parseLinkHeader(header string, rel string) (string, error) {
	// Link头格式示例: <https://api.github.com/repositories/xxx/commits?page=2&per_page=1>; rel="next", <https://api.github.com/repositories/xxx/commits?page=100&per_page=1>; rel="last"
	links := strings.Split(header, ",")
	for _, link := range links {
		parts := strings.Split(strings.TrimSpace(link), ";")
		if len(parts) < 2 {
			continue
		}
		// 提取URL部分,去掉<>
		urlPart := strings.Trim(parts[0], "<>")
		// 提取rel属性
		relPart := strings.TrimSpace(parts[1])
		if strings.HasPrefix(relPart, `rel="`) && strings.HasSuffix(relPart, `"`) {
			currentRel := strings.Trim(relPart, `rel="`)
			currentRel = strings.TrimSuffix(currentRel, `"`)
			if currentRel == rel {
				return urlPart, nil
			}
		}
	}
	return "", fmt.Errorf("rel=%s not found in link header", rel)
}

func main() {
	count, err := getCommitsCount("golang", "go")
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Printf("Total commits: %d\n", count)
}

关键细节说明

  • Link头解析:Go的http.Response.Header.Get("Link")可以拿到原始的Link头字符串,需要自己按GitHub的Link格式( <URL>; rel="xxx")拆分解析。
  • 提取指定rel的链接:parseLinkHeader函数遍历所有link项,匹配rel="last"的条目,提取对应的URL。
  • 解析page参数:使用net/url包解析URL的query参数,获取page值后转换为整数,这个值就是总页数,因为每页1条提交,所以总页数等于总提交数。
  • 边界情况处理:如果没有Link头,说明仓库提交数≤1,直接返回1(如果请求成功)。

内容的提问来源于stack exchange,提问作者perceptr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 02:55:32