Search code examples
goconcurrencywebservermutexerror-correction

The Go Programming Language book example server2 is wrong?


I am going through The Go programming Language Book. In chapter 1, server 2 example: Book's code the mutex is used to prevent the race condition. However i copied the code and tried to run it and it's giving inconsistent result. Is the code in the example wrong?

Here's how i used the code:

server.go

package server

import (
    "fmt"
    "log"
    "net/http"
    "sync"
)

const (
    PORT string = ":8000"
)

var count int

var mu sync.Mutex

func Run() {
    http.HandleFunc("/", handler)
    http.HandleFunc("/count", counter)
    fmt.Printf("Server is listening on port: %s\n", PORT)
    log.Fatal(http.ListenAndServe(PORT, nil))
}

func handler(w http.ResponseWriter, r *http.Request) {
    mu.Lock()
    count++
    mu.Unlock()
    fmt.Fprintf(w, "URL Path = %q\n", r.URL.Path)
}

func counter(w http.ResponseWriter, r *http.Request) {
    mu.Lock()
    fmt.Fprintf(w, "Count = %d\n", count)
    mu.Unlock()
}

main.go

package main

import "book/server"

func main() {
    server.Run()
}

When i run: go run main.go and visit the two pages localhost:8000 and localhost:8000/count

  1. Whenever I refresh the /count page the count increases. Why?
  2. Whenever I refresh the / and /count page the count shown are inconsistently increased? Not according to the number of refreshes. Why?

I was expecting the count would only increase when i visit / page and not /count page and it would increase according to the number of refreshes I did.


Solution

  • That's because when you test the web page with a browser, most of the time, the browser will send a request to http://localhost:8000/favicon.ico too. See the screenshot below:

    enter image description here

    There is not a dedicated handler for /favicon.ico, and it matches /, so it will be handled by server.handler.

    It's recommended to use other tools for testing such kind of demos. For example, curl:

    $ curl 'http://localhost:8000/'
    $ curl 'http://localhost:8000/count'