Golang初级实战:开发一个简单的GitHub统计工具 Go语言REST API集成

6次阅读

用 net/http 编写轻量 github 用户仓库数查询服务:校验用户名格式,设 user-agent 和超时,用 url.url 构建请求,正确解析 json 响应中的 public_repos 字段。

Golang初级实战:开发一个简单的GitHub统计工具 Go语言REST API集成

怎么用 go 写个能查 github 用户仓库数的 HTTP 服务

直接上手:用 net/http 起一个最简 API,不引入框架,避免初期被路由、中间件绕晕。重点是让请求能发出去、响应能收回来、JSON 能解出来。

常见错误现象:json: cannot unmarshal Object into Go Struct —— 大多因为 GitHub API 返回结构嵌套深,但你定义的 struct 字段没对齐(比如漏了 user 外层包了一层 data),或字段名没加 json tag。

  • GitHub rest api v3 的用户信息接口GET https://api.github.com/users/{username},返回里 public_repos整型字段,直接映射到 int 即可
  • 必须设 User-Agent 请求头,否则 GitHub 会返回 403 Forbidden(错误信息里明确写 "message": "API rate limit exceeded" 或更直白的 "message": "You must provide a User-Agent header."
  • 别用 http.Get 硬编码 URL 拼接,改用 url.URL + url.Values 构建,防特殊字符(比如用户名含 +/

为什么不用 github.com/google/go-github/v52 这类 SDK

不是不能用,而是初级阶段过早引入 SDK,反而掩盖了 HTTP 请求本质和错误处理逻辑。SDK 把重试、分页、鉴权都封装了,但你连 404422 都分不清时,SDK 只会让错误更难定位。

使用场景:只查单个用户公开仓库数,不需要分页、组织成员列表、PR 状态等——这种需求,手写 http.Client + json.Unmarshal 更轻、更可控。

立即学习go语言免费学习笔记(深入)”;

  • SDK 默认启用 rate limit 自动等待,但你根本没配 Token,它就卡在那儿不动,控制台也没提示
  • SDK 返回的 struct 字段名常带下划线(如 Public_Repos),而 Go 标准库 json 解析默认按首字母大小写匹配,容易漏字段
  • 如果后续要加缓存或日志,SDK 的调用链埋点比原生 Do 调用难插桩

怎么安全传入用户名并防止路径遍历或注入

GitHub 用户名规则是:只能含 ASCII 字母、数字、短横线(-),且不能以短横线开头或结尾,长度 1–39。不校验就直接拼进 URL,可能被构造为 ../../etc/passwd 类路径穿越(虽然 GitHub API 不走文件系统,但养成习惯很重要)。

参数差异:URL 路径参数(path param)和查询参数(query param)处理方式不同。用户名必须是 path param,因为它是资源标识符;其他如 per_page 才该放 query。

  • regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9-]{0,38}[a-zA-Z0-9]$`) 做白名单校验,比 strings.Contains 黑名单更可靠
  • 校验失败立刻返回 400 Bad Request 并带上具体错误原因(比如 "invalid username format"),别吞掉或返回空 JSON
  • 别在日志里打印完整请求 URL,防止用户名被误记入日志系统(尤其部署后有人测 adminroot 这类敏感词)

本地调试时总遇到 connection refused 或 timeout 怎么办

八成是没设超时,http.DefaultClient 的默认 Transport 没配 Timeout,一卡就是几十秒,看着像挂了。Go 的 HTTP 客户端默认不设限,得自己管。

性能 / 兼容性影响:不设超时,线上并发高时 goroutine 积压,内存暴涨;本地调试时则表现为命令行卡住、IDE 调试器失联。

  • 必须显式创建 http.Client,设置 Timeout: 10 * time.Second
  • 别忽略 resp.Body.Close(),否则连接不释放,跑几次就触发 too many open files
  • curl -v http://localhost:8080/user/octocat 看原始响应头和状态码,比浏览器更准——浏览器可能缓存 304,而你代码其实已报错

事情说清了就结束

text=ZqhQzanResources