/

go-github-api

#使用Go從GitHub獲取存儲庫列表
在這篇文章中,我將使用Go的net/http標準庫包,不使用任何附加庫,向GitHub API請求公共存儲庫的信息。
GitHub有一個很好的公共API稱為Search,您可以在https://developer.github.com/v3/search/#search-repositories上查看。
具體而言,我對獲取當前擁有1萬個以上星標的Go存儲庫感興趣。
我們可以傳遞一個查詢來獲取我們想要的內容。查看Search API文檔,我們需要對https://api.github.com/search/repositories進行HTTP GET請求,並傳遞查詢?q=stars:>=10000+language:go&sort=stars&order=desc:給我一個星標超過1萬個、使用Go語言的存儲庫,按星標數量進行排序。
最簡單的程式碼片段:我們使用net/http中的http.Get函數進行請求,並使用ioutil.ReadAll函數讀取返回的內容:

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
package main

import (
"io/ioutil"
"log"
"net/http"
)

func main() {
res, err := http.Get("https://api.github.com/search/repositories?q=stars:>=10000+language:go&sort=stars&order=desc")

if err != nil {
log.Fatal(err)
}

body, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatal(err)
}
if res.StatusCode != 200 {
log.Fatal("Unexpected status code", res.StatusCode)
}

log.Printf("Body: %s\n", body)
}


就像您所看到的那樣,它並不易於閱讀。您可以將返回的內容使用在線格式化工具來理解實際結構。

現在讓我們處理JSON並從中生成一個漂亮的表格。
如果您對JSON主題還不熟悉,可以查看我有關使用Go處理JSON的初步指南[/go-json/]。

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
package main

import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"text/tabwriter"
"time"
)

// Owner是存儲庫擁有者
type Owner struct {
Login string
}

// Item是單個存儲庫的數據結構
type Item struct {
ID int
Name string
FullName string `json:"full\_name"`
Owner Owner
Description string
CreatedAt string `json:"created\_at"`
StargazersCount int `json:"stargazers\_count"`
}

// JSONData包含GitHub API的響應
type JSONData struct {
Count int `json:"total\_count"`
Items []Item
}

func main() {
res, err := http.Get("https://api.github.com/search/repositories?q=stars:>=10000+language:go&sort=stars&order=desc")
if err != nil {
log.Fatal(err)
}
body, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatal(err)
}
if res.StatusCode != http.StatusOK {
log.Fatal("Unexpected status code", res.StatusCode)
}
data := JSONData{}
err = json.Unmarshal(body, &data)
if err != nil {
log.Fatal(err)
}
printData(data)
}

func printData(data JSONData) {
log.Printf("Repositories found: %d", data.Count)
const format = "%v\t%v\t%v\t%v\t\n"
tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0)
fmt.Fprintf(tw, format, "Repository", "Stars", "Created at", "Description")
fmt.Fprintf(tw, format, "----------", "-----", "----------", "----------")
for \_, i := range data.Items {
desc := i.Description
if len(desc) > 50 {
desc = string(desc[:50]) + "..."
}
t, err := time.Parse(time.RFC3339, i.CreatedAt)
if err != nil {
log.Fatal(err)
}
fmt.Fprintf(tw, format, i.FullName, i.StargazersCount, t.Year(), desc)
}
tw.Flush()
}

上面的代碼創建了3個結構體來處理GitHub提供的JSON。JSONData是主容器,Items是一個Item的切片,即存儲庫結構體,在Item內部,Owner包含存儲庫擁有者的數據。
在得到由http.Get返回的HTTP響應res之後,我們使用res.Body提取內容,並使用ioutil.ReadAll將其全部讀取到body中。
在確認res.StatusCodehttp.StatusOK常數(對應200)匹配之後,我們使用json.Unmarshal將JSON解析為我們的JSONData結構體data,然後將其傳遞給printData函數。
printData函數內部,我實例化了一個tabwriter.Writer,然後根據需要依次處理和格式化JSON數據,以生成漂亮的表格佈局: