使用Golang操作GitHub API的实战指南

使用Golang操作GitHub API的实战指南 packagemain #28: 如何在 Go 中使用 GitHub API

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

  1. 访问 https://github.com/settings/tokens
  2. 生成新的Personal Access Token
  3. 选择需要的权限范围(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即可。

回到顶部