1 回复
更多关于使用Golang操作GitHub API的实战指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用Golang操作GitHub API的实战指南
以下是一个完整的Go程序示例,演示如何使用GitHub API进行常见操作:
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"time"
"github.com/google/go-github/v50/github"
"golang.org/x/oauth2"
)
// GitHub客户端配置
type GitHubClient struct {
client *github.Client
ctx context.Context
}
// 初始化GitHub客户端
func NewGitHubClient(token string) *GitHubClient {
ctx := context.Background()
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: token},
)
tc := oauth2.NewClient(ctx, ts)
return &GitHubClient{
client: github.NewClient(tc),
ctx: ctx,
}
}
// 获取用户信息
func (gc *GitHubClient) GetUserInfo(username string) (*github.User, error) {
user, _, err := gc.client.Users.Get(gc.ctx, username)
if err != nil {
return nil, fmt.Errorf("获取用户信息失败: %v", err)
}
return user, nil
}
// 列出用户的仓库
func (gc *GitHubClient) ListUserRepos(username string, opts *github.RepositoryListOptions) ([]*github.Repository, error) {
repos, _, err := gc.client.Repositories.List(gc.ctx, username, opts)
if err != nil {
return nil, fmt.Errorf("列出仓库失败: %v", err)
}
return repos, nil
}
// 创建新的仓库
func (gc *GitHubClient) CreateRepository(repo *github.Repository) (*github.Repository, error) {
newRepo, _, err := gc.client.Repositories.Create(gc.ctx, "", repo)
if err != nil {
return nil, fmt.Errorf("创建仓库失败: %v", err)
}
return newRepo, nil
}
// 创建Issue
func (gc *GitHubClient) CreateIssue(owner, repo string, issue *github.IssueRequest) (*github.Issue, error) {
newIssue, _, err := gc.client.Issues.Create(gc.ctx, owner, repo, issue)
if err != nil {
return nil, fmt.Errorf("创建Issue失败: %v", err)
}
return newIssue, nil
}
// 获取仓库的star数量
func (gc *GitHubClient) GetRepoStargazers(owner, repo string) ([]*github.Stargazer, error) {
opts := &github.ListOptions{PerPage: 100}
var allStargazers []*github.Stargazer
for {
stargazers, resp, err := gc.client.Activity.ListStargazers(gc.ctx, owner, repo, opts)
if err != nil {
return nil, fmt.Errorf("获取star用户失败: %v", err)
}
allStargazers = append(allStargazers, stargazers...)
if resp.NextPage == 0 {
break
}
opts.Page = resp.NextPage
}
return allStargazers, nil
}
// 使用原生HTTP请求调用GitHub API
func CallGitHubAPIWithHTTP(token, endpoint string) (map[string]interface{}, error) {
client := &http.Client{Timeout: 10 * time.Second}
req, err := http.NewRequest("GET", "https://api.github.com"+endpoint, nil)
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "token "+token)
req.Header.Set("Accept", "application/vnd.github.v3+json")
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var result map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, err
}
return result, nil
}
func main() {
// 替换为你的GitHub Personal Access Token
token := "your_github_personal_access_token"
// 初始化客户端
client := NewGitHubClient(token)
// 示例1: 获取用户信息
user, err := client.GetUserInfo("octocat")
if err != nil {
log.Printf("错误: %v", err)
} else {
fmt.Printf("用户: %s\n", *user.Login)
fmt.Printf姓名: %s\n", user.GetName())
fmt.Printf("仓库数: %d\n", user.GetPublicRepos())
}
// 示例2: 列出仓库
repoOpts := &github.RepositoryListOptions{
Type: "public",
Sort: "updated",
Direction: "desc",
ListOptions: github.ListOptions{
PerPage: 10,
},
}
repos, err := client.ListUserRepos("golang", repoOpts)
if err != nil {
log.Printf("错误: %v", err)
} else {
fmt.Println("\n前10个Go仓库:")
for _, repo := range repos {
fmt.Printf("- %s: %s\n", *repo.Name, *repo.Description)
}
}
// 示例3: 创建Issue
issueRequest := &github.IssueRequest{
Title: github.String("测试Issue"),
Body: github.String("这是一个通过Go程序创建的测试Issue"),
Labels: &[]string{"bug", "enhancement"},
}
// 注意: 需要替换为你有权限的仓库
// issue, err := client.CreateIssue("owner", "repo", issueRequest)
// if err != nil {
// log.Printf("错误: %v", err)
// } else {
// fmt.Printf("创建的Issue: %s\n", *issue.Title)
// }
// 示例4: 使用原生HTTP请求
result, err := CallGitHubAPIWithHTTP(token, "/user")
if err != nil {
log.Printf("HTTP请求错误: %v", err)
} else {
fmt.Printf("\n通过HTTP获取的用户信息:\n")
fmt.Printf("登录名: %v\n", result["login"])
}
// 示例5: 获取仓库star信息
stargazers, err := client.GetRepoStargazers("golang", "go")
if err != nil {
log.Printf("错误: %v", err)
} else {
fmt.Printf("\nGo仓库的star数量: %d\n", len(stargazers))
}
}
安装依赖
go get github.com/google/go-github/v50/github
go get golang.org/x/oauth2
配置GitHub Token
- 访问 https://github.com/settings/tokens
- 生成新的Personal Access Token
- 选择需要的权限范围(repo, user, admin:org等)
高级功能示例
// 搜索仓库
func SearchRepositories(client *GitHubClient, query string) (*github.RepositoriesSearchResult, error) {
result, _, err := client.client.Search.Repositories(client.ctx, query, &github.SearchOptions{
Sort: "stars",
Order: "desc",
})
return result, err
}
// 获取仓库的贡献者
func GetRepoContributors(client *GitHubClient, owner, repo string) ([]*github.Contributor, error) {
contributors, _, err := client.client.Repositories.ListContributors(client.ctx, owner, repo, &github.ListContributorsOptions{})
return contributors, err
}
// 创建Webhook
func CreateWebhook(client *GitHubClient, owner, repo string, hook *github.Hook) (*github.Hook, error) {
newHook, _, err := client.client.Repositories.CreateHook(client.ctx, owner, repo, hook)
return newHook, err
}
// 处理分页的通用函数
func ListAllPages[T any](listFunc func(opts *github.ListOptions) ([]T, *github.Response, error)) ([]T, error) {
opts := &github.ListOptions{PerPage: 100}
var allItems []T
for {
items, resp, err := listFunc(opts)
if err != nil {
return nil, err
}
allItems = append(allItems, items...)
if resp.NextPage == 0 {
break
}
opts.Page = resp.NextPage
}
return allItems, nil
}
错误处理最佳实践
// 带重试的API调用
func CallWithRetry(fn func() error, maxRetries int) error {
var lastErr error
for i := 0; i < maxRetries; i++ {
if err := fn(); err != nil {
lastErr = err
// 检查是否是速率限制错误
if _, ok := err.(*github.RateLimitError); ok {
time.Sleep(time.Minute) // 等待1分钟
continue
}
// 检查是否是临时错误
if _, ok := err.(*github.AbuseRateLimitError); ok {
time.Sleep(time.Second * 30)
continue
}
return err
}
return nil
}
return fmt.Errorf("重试%d次后失败: %v", maxRetries, lastErr)
}
这个实战指南提供了完整的Go代码示例,涵盖了GitHub API的主要功能,包括认证、用户信息获取、仓库操作、Issue管理等。所有代码都可以直接运行,只需要替换为有效的GitHub Token即可。


