Go HTML template

Issue

I have created a simple scraper that takes the top 10 news from a website and returns a JSON with the title and the score. I want to pass the title and the score as HTML template so I can generate a webpage. I’m not familiar with the templating Go language and I don’t know how to pass the values for each of the links. Here is the HTML code that I should use and my implementation for now:

<!DOCTYPE html>
<html>
   <head><linkrel="stylesheet" href="https://unpkg.com/mvp.css"
      />
   </head>
   <body>
      <h1>{{.PageTitle}}</h1>
      <ul>
         {{range .Links}}
         <li>{{.Title}}: {{.Score}}</li>
         {{end}}
      </ul>
   </body>
</html>

My code:

package main
    
    import (
        "encoding/json"
        "html/template"
        "log"
        "net/http"
        "strconv"
    )
    
    type TopStories struct {
        Title string `json:"title"`
        Score int    `json:"score"`
    }
    
    type TopStoriesPayload struct {
        TopStories []TopStories
    }
    
    type NewsScraper struct {
        url  string
        Data []TopStories
    }
    
    type templateData struct {
        PageTitle string
        Data      []TopStories
    
    }
    
    func NewNewsScraper(url string) *NewsScraper {
        return &NewsScraper{url: url}
    }
    
    func Top10Stories() []string {
        req, err := http.NewRequest("GET", "https://hacker-news.firebaseio.com/v0/topstories.json", nil)
        if err != nil {
            log.Fatal(err)
        }
        resp, err := http.DefaultClient.Do(req)
        if err != nil {
            log.Fatal(err)
        }
        var IDs []int
        json.NewDecoder(resp.Body).Decode(&IDs)
        IDs = IDs[:10]
        var IDsString []string
        for _, id := range IDs {
            IDsString = append(IDsString, strconv.Itoa(id))
        }
        return IDsString
    }
    
    func (n *NewsScraper) GetTopStories() {
        req, err := http.NewRequest("GET", n.url, nil)
        if err != nil {
            log.Fatal(err)
        }
    
        for _, id := range Top10Stories() {
            req.URL.Path = "/v0/item/" + id + ".json"
            resp, err := http.DefaultClient.Do(req)
            if err != nil {
                log.Fatal(err)
            }
            var topStory TopStories
            json.NewDecoder(resp.Body).Decode(&topStory)
            n.Data = append(n.Data, topStory)
        }
    }
    
    //create html template handler for top stories
    func HTMLHandler(w http.ResponseWriter, r *http.Request) {
        scraper := NewNewsScraper("https://hacker-news.firebaseio.com")
        scraper.GetTopStories()
        tmpl:= template.Must(template.ParseFiles("template.html"))
        data := templateData{
            PageTitle: "Top Stories",
            Data :[]TopStories{
                //what should I put here?
            },
        }
        tmpl.Execute(w, data)
    }
    
    func main() {
        mux := http.NewServeMux()
        mux.HandleFunc("/top", HTMLHandler)
        http.ListenAndServe(":8080", mux)
    }

Solution

I see three issues with your code:

a) The template.html file should have space between link & rel

<linkrel="stylesheet" href="https://unpkg.com/mvp.css"/>

to

<link rel="stylesheet" href="https://unpkg.com/mvp.css"/>

b) The template.html file should contain .Data instead of .Links.

c) The go code should be replaced from the below

Data :[]TopStories{ 
  //what should I put here?
},

to

Data : scraper.Data,

Answered By – Kishore

Answer Checked By – Candace Johnson (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.