github.go
package github
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"strings"
"time"
)
//通过issue跟踪接口,发送HTTP请求获取json信息
const IssuesURL = "https://developer.github.com/v3/search/issues"
type IssuesSearchResult struct {
TotalCount int `json:"total_count"`
Items []*Issue
}
type Issue struct {
Number int
HTMLURL string `json:"html_url"`
Title string
State string
User *User
CreatedAt time.Time `json:"created_at"`
Body string //markdown格式
}
type User struct {
Login string
HTMLURL string `json:"html_url"`
}
func SearchIssues(terms []string) (*IssuesSearchResult, error) {
q := url.QueryEscape(strings.Join(terms, " ")) //预处理
//string.join 将terms展开拼接成一个字符串,并用" "分隔
//url.QueryEscape函数对字符串进行转码使之可以安全的用在URL查询里。相当于url预处理
resp, err := http.Get(IssuesURL + "?q=" + q) //发送URL获取回复, 这是一个HTTP请求的回复
if err != nil {
return nil, err //失败后返回
}
//defer resp.body.Close()
if resp.StatusCode != http.StatusOK { //StatusOK = '200'
resp.Body.Close()
return nil, fmt.Errorf("search query failed:%s", resp.Status)
//Errorf根据format参数生成格式化字符串并返回一个包含该字符串的错误。
}
var result IssuesSearchResult
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
//NewDecoder创建一个从resp.Body读取并解码json对象的*Decoder,解码器有自己的缓冲,并可能超前读取部分json数据。
//Decode从输入流读取下一个json编码值并保存在reuslt指向的值里.这种方法全名叫流式解码器,与Unmarshal的区别是,
//Unmarshal是从整个[]byte中解码出一个json,而流式解码器是从[]byte中解解码出多个json
resp.Body.Close()
return nil, err
}
resp.Body.Close()
return &result, nil
}
main.go
package main
import (
"fmt"
"go_learn_1/project_day01/ch4/github"
"log"
"os"
)
func main() {
result, err := github.SearchIssues(os.Args[1:])
if err != nil {
log.Fatal(err)
}
fmt.Printf("%d issues:\n, result.TotalCount")
for _, item := range result.Items {
fmt.Printf("#%-5d %9.9s %.55s\n", item.Number, item.User.Login, item.Title)
}
}