如何在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
相关产品推荐
相关产品推荐

