使用 Go 透過 GraphQL API 存取 GitHub 資料

做法

申請令牌

先至 GitHub 的 Personal access tokens 頁面申請一個存取令牌。根據需求選擇令牌的作用域,例如要存取公開的儲存庫,就將 public_repo 打勾。

探索

使用 GitHub GraphQL API Explorer 進行探索。

實作

新增 main.go 檔:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package main

import (
"bytes"
"context"
"encoding/json"
"fmt"
"log"
"net/http"
)

// 根據查詢條件的回應結果定義一個回應結構體
type Response struct {
Data struct {
User struct {
Repositories struct {
Nodes []struct {
Name string `json:"name"`
} `json:"nodes"`
} `json:"repositories"`
} `json:"user"`
} `json:"data"`
}

func main() {
// 獲取資源
response, err := Fetch(context.Background())

if err != nil {
log.Println(err.Error())
}

fmt.Println(response)
}

// 獲取資源
func Fetch(ctx context.Context) (Response, error) {
response := Response{}

// 制定查詢條件
q := struct {
Query string `json:"query"`
}{
Query: `
query {
user(login: "memochou1993") {
repositories(first: 10) {
nodes {
name
}
}
}
}
`,
}

body := &bytes.Buffer{}

// 序列化到 body 變數
if err := json.NewEncoder(body).Encode(q); err != nil {
return response, err
}

// 建立請求
req, err := http.NewRequest(http.MethodPost, "https://api.github.com/graphql", body)

if err != nil {
return response, err
}

req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", "<TOKEN>"))

// 發送請求
resp, err := http.DefaultClient.Do(req.WithContext(ctx))

if err != nil {
return response, err
}

defer func() {
if err := resp.Body.Close(); err != nil {
log.Println(err.Error())
}
}()

// 反序列化到 response 變數
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
return response, err
}

return response, nil
}

輸出結果:

1
{{{{[{kuntai} {portfolio} {surl} {memochou1993.github.io} {blog} {jwt-lumen} {doaj} {laravel-foundation-preset} {journal} {post}]}}}}

補充

回應的結構體可以使用 JSON-to-Go 這個線上工具將 JSON 轉換成 Go 的結構體。

程式碼

參考資料