所有应用程序应具有的基本Web调整

Currently my web app is just a router and handlers.

What are some important things I am missing to make this production worthy?

  1. I believe I have to set the # of procs to ensure this uses maximum goroutines?

  2. Should I be using output buffering?

Anything else you see missing that is best-practise?

var (
  templates = template.Must(template.ParseFiles("templates/home.html")
)

func main() {
  r := mux.NewRouter()
  r.HandleFunc("/", WelcomeHandler)

  http.ListenAndServe(":9000", r)
}

func WelcomeHandler(w http.ResponseWriter, r *http.Request) {
    homePage, err := api.LoadHomePage()
    if err != nil {
    }
    tmpl := "home"
    renderTemplate(w, tmpl, homePage)
}

func renderTemplate(w http.ResponseWriter, tmpl string, hp *HomePage) {

    err := templates.ExecuteTemplate(w, tmpl+".html", hp)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}
  1. You don't need to set/change runtime.GOMAXPROCS() as since Go 1.5 it defaults to the number of available CPU cores.

  2. Buffering output? From the performance point of view, you don't need to. But there may be other considerations for which you may.

For example, your renderTemplate() function may potentially panic. If executing the template starts writing to the output, it involves setting the HTTP response code and other headers prior to writing data. And if a template execution error occurs after that, it will return an error, and so your code attempts to send back an error response. At this point HTTP headers are already written, and this http.Error() function will try to set headers again => panic.

One way to avoid this is to first render the template into a buffer (e.g. bytes.Buffer), and if no error is returned by the template execution, then you can write the content of the buffer to the response writer. If error occurs, then of course you won't write the content of the buffer, but send back an error response just like you did.

To sum it up, your code is production ready performance-wise (excluding the way you handle template execution errors).

  1. WelcomeHandler should return when err != nil is true.
  2. Log the error when one is hit to help investigation.
  3. Place templates = template.Must(template.ParseFiles("templates/home.html") in the init. Split it into separate lines. If template.ParseFiles returns an then error make a Fatal log. And if you have multiple templates to initialize then initialize them in goroutines with a common WaitGroup to speed up the startup.
  4. Since you are using mux, HTTP Server is too clean with its URLs might also be good to know.
  5. You might also want to reconsider the decision of letting the user's know why they got the http.StatusInternalServerError response.
  6. Setting the GOMAXPROCS > 1 if you have more the one core would definitely be a good idea but I would keep it less than number of cores available.