In this blog post, we will explore how to use the Go net/http
stdlib package to retrieve information about public repositories from the GitHub API. We will specifically focus on obtaining Go repositories with more than 10k stars.
GitHub provides a convenient public API called Search, which you can find at https://developer.github.com/v3/search/#search-repositories. By making an HTTP GET request to https://api.github.com/search/repositories?q=stars:>=10000+language:go&sort=stars&order=desc
, we can retrieve the repositories that match our criteria: Go repositories with more than 10k stars, sorted by the number of stars.
Let’s take a look at a simple snippet of code that uses http.Get
from net/http
to make the request and ioutil.ReadAll
to read the response body:
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)
}
The output of this code may not be very readable, but you can use an online JSON formatter to make it easier to understand the structure.
To process the JSON response and generate a table from it, we can use the following code example:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"text/tabwriter"
"time"
)
type Owner struct {
Login string
}
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"`
}
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()
}
This code defines three structs to unmarshal the JSON response from GitHub: JSONData
, Item
, and Owner
. We use http.Get
to retrieve the response body, ioutil.ReadAll
to read it, and json.Unmarshal
to unmarshal the JSON into our JSONData
struct. The printData
function processes the data and generates a nicely formatted table using tabwriter.Writer
.
By running this code, you can retrieve and display the repositories along with their star count, creation date, and description in a readable format.
Tags: go, GitHub API, net/http, JSON processing