douru5373
2016-03-12 02:41 阅读 6

在浏览器中显示Go App

I wrote an app that makes a request to an API and gets a JSON response. When I run the app it displays the json in the terminal.

go run main.go

I want to make this run in the browser and I found this, which allowed me to print a string to the browser.

     func handler(w http.ResponseWriter, r *http.Request) {
       fmt.Fprintf(w, "This is a string")
   }

Then in main

http.HandleFunc("/", handler) 
log.Fatal(http.ListenAndServe("localhost:8000", nil))

Now that I have a string being printed to the screen and I have a json response coming from the api I am using, how can I add the json response to the browser instead of the string?

Would it be best to put the response into a string then just bring it to the browser?

Currently I am printing the json response to the terminal like this,

type Payload struct {
        Page    int
        Results []Data 
}

type Data struct {
        PosterPath       string  `json:"poster_path"`
        Adult            bool    `json:"adult"`
        Overview         string  `json:"overview"`
        ReleaseDate      string  `json:"release_date"`
        GenreIds         []int   `json:"genre_ids"`
        Id               int     `json:"id"`
        OriginalTitle    string  `json:"original_title"`
        OriginalLanguage string  `json:"original_language"`
        Title            string  `json:"title"`
        BackdropPath     string  `json:"backdrop_path"`
        Popularity       float64 `json:"popularity"`
        VoteCount        int     `json:"vote_count"`
        Video            bool    `json:"video"`
        VoteAverage      float64 `json:"vote_average"`
}

Then inside main() I do this,

    for i := 0; i < len(p.Results); i++ {
            fmt.Println(
            ImgUrl+p.Results[i].PosterPath, "
", p.Results[i].Adult,
            p.Results[i].Overview, "
", p.Results[i].ReleaseDate,
            p.Results[i].GenreIds, "
", p.Results[i].Id,
            p.Results[i].OriginalTitle, "
", p.Results[i].OriginalLanguage,
            p.Results[i].Title, "
", ImgUrl+p.Results[i].BackdropPath,
            p.Results[i].Popularity, "
", p.Results[i].VoteCount,
            p.Results[i].Video, "
", p.Results[i].VoteAverage,
            )

What would be the Go way to do this for building web applications? My end goal here is to take user input and recreate my api call based on the information they provide.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

1条回答 默认 最新

  • 已采纳
    dongsisui7562 dongsisui7562 2016-03-12 02:59

    If you are fine with directly sending the response from the API to your users then use io.Copy. You can check if the api request was successful before relaying it to the users and send an error if it did not.

    Some APIs send information in headers like how you are doing with the rate limiting. So you can check headers as well before relaying.

    func handler(w http.ResponseWriter, r *http.Request) {
        resp, err := http.Get("http://jsonplaceholder.typicode.com/posts") // your request to the api
    
        w.Header().Set("Content-Type", "application/javascript")
    
        if err == nil && resp.StatusCode == http.StatusOK {
            io.Copy(w, resp.Body)
        } else {
            json.NewEncoder(w).Encode(err)
        }
    }
    

    This avoids making any new allocations on your app.

    If you want to send your clients html as stated in comments, use the html/template package.

    You can of course prepare a html string manually and send it to the clients. But I think its obvious that using templates makes the code cleaner and maintainable. It also provides autoescaping.

    For example following would render the Overview section of each of your Results from the Payload p

    func handler(w http.ResponseWriter, r *http.Request) {
        // Make your api call and prepare the `Payload` object (from your example in the question)
    
        for i := 0; i < len(p.Results); i++ {
           fmt.Println(p.Results[i].Overview) // Prints to your terminal
        }
    
        // Following sends same information as above to the browser as html
    
        t, err := template.New("foo").Parse(`
          {{define "T"}}
            <html><ul>{{range .Results}}<li>{{.Overview}}</li>{{end}}</ul></html>
          {{end}}`)
        err = t.ExecuteTemplate(w, "T", p) // This writes the client response
    }
    
    点赞 评论 复制链接分享

相关推荐