ex4.10git
package main import ( "flag" "fmt" "log" "os" "time" "gopl.io/ch4/github" ) var m = flag.Int("m", 0, "positive: query issues created during recently m months;\nnegative: query issues created before -m months") func main() { // -m 1 一月之內:created:2019-01-20...2019-02-20 // -m 12 一年之內:created:2018-02-20...2019-02-20 // -m -12 超過一年:created:<2018-02-20 flag.Parse() q := os.Args[1:] for i, v := range q { if v == "-m" { copy(q[i:], q[i+2:]) q = q[0 : len(q)-2] break } } if *m > 0 { end := time.Now() start := end.AddDate(0, -*m, 0) log.Println(start) q = append(q, "created:"+start.Format("2006-01-02")+".."+end.Format("2006-01-02")) } else if *m < 0 { end := time.Now().AddDate(0, *m, 0) q = append(q, "created:<"+end.Format("2006-01-02")) } log.Println(q) result, err := github.SearchIssues(q) 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) } }
ex4.11github
ex4.12json
package index import ( "crypto/tls" "encoding/json" "fmt" "io/ioutil" "net/http" "os" "strings" "sync" ) const MaxNum = 20 const XkcdUrl = "https://xkcd.com" const IndexDir = "C:/Users/Kylin/workspace/go/src/gobook/ch4/ex4.12/data/db.json" var wg sync.WaitGroup var limiter = make(chan struct{}, 20) type XkcdDb []XkcdInfo type XkcdInfo struct { Month string Num int Link string Year string News string SafeTitle string `json:"safe_title"` Transcript string Alt string Img string Title string Day string } var initSync sync.Once var db XkcdDb func init() { initSync.Do(func() { content, err := ioutil.ReadFile(IndexDir) if err != nil { panic(err) } err = json.Unmarshal(content, &db) if err != nil { panic(err) } }) } func BuildIndex() { db := make(XkcdDb, MaxNum+1) ch := make(chan *XkcdInfo, MaxNum) for i := 1; i <= MaxNum; i++ { wg.Add(1) go getIndex(i, ch) } go func() { for v := range ch { fmt.Println(v.Num) db[v.Num] = *v } }() wg.Wait() close(ch) sdb, err := json.Marshal(db) if err != nil { fmt.Println(err) return } err = ioutil.WriteFile(IndexDir, sdb, os.ModePerm) if err != nil { fmt.Println(err) } } func getIndex(num int, ch chan *XkcdInfo) { limiter <- struct{}{} defer wg.Done() defer func() { <-limiter }() url := fmt.Sprintf("%s/%d/info.0.json", XkcdUrl, num) tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}} client := &http.Client{Transport: tr} resp, err := client.Get(url) if err != nil { fmt.Println(url, err) return } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { fmt.Printf("%s:%d %s\n", url, resp.StatusCode, resp.Status) return } content, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println(err) return } xkcdInfo := XkcdInfo{} err = json.Unmarshal(content, &xkcdInfo) if err != nil { fmt.Println(err) return } ch <- &xkcdInfo } func Search(id int, q string) (res XkcdDb) { if id == 0 && q == "" { return db } for i, info := range db { if i == id && i != 0 { res = append(res, info) return } if q != "" && strings.Contains(info.Title, q) { res = append(res, info) } } return res }
package main import ( "flag" "fmt" "gobook/ch4/ex4.12/index" ) var id = flag.Int("i", 0, "the num of the content,startinf from 1.") var title = flag.String("t", "", "the title to search for") func main() { // 構建離線索引 //index.BuildIndex() flag.Parse() res := index.Search(*id, *title) fmt.Printf("Total:%d\n", len(res)) for _, info := range res { fmt.Printf("Url:%s/%d\n", index.XkcdUrl, info.Num) fmt.Println(info.Transcript) } }
ex4.13api
package main import ( "encoding/json" "fmt" "io/ioutil" "net/http" "net/url" "os" "strings" "sync" ) const apikey = "837a1b8b" const apiUrl = "http://www.omdbapi.com/" type moveInfo struct { Title string Year string Poster string } // OMDb API: http://www.omdbapi.com/?i=tt3896198&apikey=837a1b8b func getPoster(name string) { resp, err := http.Get(fmt.Sprintf("%s?t=%s&apikey=%s", apiUrl, url.QueryEscape(name), apikey)) if err != nil { fmt.Println(err) return } defer resp.Body.Close() binfo, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println(err) return } minfo := moveInfo{} err = json.Unmarshal(binfo, &minfo) if err != nil { fmt.Println(err) return } poster := minfo.Poster if poster != "" { downloadPoster(poster) } } func downloadPoster(url string) { resp, err := http.Get(url) if err != nil { fmt.Println(err) return } defer resp.Body.Close() bcontent, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println(err) return } pos := strings.LastIndex(url, "/") if pos == -1 { fmt.Println("failed to parse the name of the poster") return } f, err := os.Create(url[pos+1:]) if err != nil { fmt.Println(err) return } defer f.Close() _, err = f.Write(bcontent) if err != nil { fmt.Println(err) } } func main() { var wg sync.WaitGroup names := os.Args[1:] for _, name := range names { wg.Add(1) go func(){ getPoster(name) wg.Done() } } wg.Wait() }