I'm trying to learn Go web programming, and here is a simple web server: it prints out the times being called.
package main
import (
"fmt"
"net/http"
)
var calls int
// HelloWorld print the times being called.
func HelloWorld(w http.ResponseWriter, r *http.Request){
calls++
fmt.Fprintf(w, "You've called me %d times", calls)
}
func main() {
fmt.Printf("Started server at http://localhost%v.\n", 5000)
http.HandleFunc("/", HelloWorld)
http.ListenAndServe(":5000", nil)
}
When I refresh the page, I got:
You've called me 1 times
You've called me 3 times
You've called me 5 times
....
Question: Why it is 1, 3, 5 times, rather than 1,2,3...? What's the order of the function HelloWorld
being called?
It is because every incoming request is routed to your
HelloWorld()
handler function, and the browser makes multiple calls under the hood, specifically to/favicon.ico
.And since your web server does not send back a valid favicon, it will request it again when you refresh the page in the browser.
Try it with Chrome: open the Developer tools (CTRL+SHIFT+I), and choose the "Network" tab. Hit refresh, and you will see 2 new entries:
Since your counter starts with
0
(default value for typeint
), you increment it once and you send back1
. Then the request forfavicon.ico
increments it again (2
), but the result is not displayed. Then if you refresh, it gets incremented again to3
and you send that back, etc.Also note that multiple goroutines can serve requests concurrently, so your solution has a race. You should synchronize access to the
calls
variable, or use thesync/atomic
package to increment the counter safely, for example:A simple "fix" to achieve what you want would be to check the request path, and if it is not the root
"/"
, don't increment, e.g.:You may also choose to only exclude requests for
favicon.ico
, e.g.: