0
  Update:  The question title can be misleading.  This was not Go's fault at all.
           See the first comment or the accepted answer.

This following code (well, almost the same) counts page views under Linux allright, but counts them double under Windows.

Can someone figure out why?

package main

import (
 "fmt"
    "http"
)

func main() {
    println("Running")
    http.HandleFunc("/", makeHomeHandler())
 http.ListenAndServe(":8080", nil)
}

// this version compiles and run OK under the Linux version of Golang
func makeHomeHandler() func(c *http.Conn, r *http.Request) {
    views := 1
    return func(c *http.Conn, r *http.Request) {
     fmt.Fprintf(c, "Counting %s, %d so far.", r.URL.Path[1:], views)
        views++
    }
}

/*
// this version compiles and run OK under the mingw version of Golang
// it uses a different argument type for the handler function,
// but the counter says "1 so far", then "3 so far", "5 so far", and so on.
func makeHomeHandler() func(c http.ResponseWriter, r *http.Request) {
    views := 1
    return func(c http.ResponseWriter, r *http.Request) {
     fmt.Fprintf(c, "Counting %s, %d so far.", r.URL.Path[1:], views)
        views++
    }
}
*/

Under Mingw:

http://localhost:8080/monkeys => Counting monkeys, 1 so far.
http://localhost:8080/monkeys => Counting monkeys, 3 so far.
http://localhost:8080/donkeys => Counting donkeys, 5 so far.

Could this be a bug?

Followup:

In fact, if I define an additional handler for another page, like:

   http.HandleFunc("/test", testPageHandler)

Wich does not have a closure, nor increments anything, the counter gets incremented anyway, but only +1:

So, still under Mingw:

http://localhost:8080/monkeys => Counting monkeys, 1 so far.
http://localhost:8080/monkeys => Counting monkeys, 3 so far.
http://localhost:8080/test   => Another handler function that does not increment "views"
http://localhost:8080/donkeys => Counting donkeys, 6 so far.

Under Linux output is as spected:

http://localhost:8080/monkeys => Counting monkeys, 1 so far.
http://localhost:8080/monkeys => Counting monkeys, 2 so far.
http://localhost:8080/test   => Another handler function that does not increment "views"
http://localhost:8080/donkeys => Counting donkeys, 3 so far.
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Sebastián Grignoli
  • 32,444
  • 17
  • 71
  • 86

1 Answers1

5

I suspect that the behaviour you're seeing is due to the browser requesting a favicon for your page and not due to Windows/mingw. In case you wonder, I'm using 6g ond Darwin, my Firefox 3.6 is also running on Mac OS X.

To underline my suspicion, try adding the following to the handler function:

fmt.Printf("Counting %s, %d so far.\n", r.URL.Path[1:], views)

Then you can see all the requests reaching your application. One request from a freshly started Firefox to the URL http://localhost:8080/chuchichaestli yields this output:

Counting chuchichaestli, 1 so far.
Counting favicon.ico, 2 so far.

because Firefox also requests the favicon for your go page.

Furthermore you're not locking/synchronising access to views even though there could be multiple concurrent requests.

distributed
  • 116
  • 1
  • 4
  • How can I lock access to `views`? – Sebastián Grignoli Mar 28 '11 at 19:59
  • As mentioned, this code is **unsafe** as it has a data race on reading/writing to the counter. The correct approach is to use something like [`n := atomic.AddInt64(&views, 1)`](https://golang.org/pkg/sync/atomic/#AddInt64https://golang.org/pkg/sync/atomic/#AddInt64) or [`expvar`](https://golang.org/pkg/expvar/). There are no [benign/safe data races](https://software.intel.com/en-us/blogs/2013/01/06/benign-data-races-what-could-possibly-go-wrong). – Dave C Apr 26 '15 at 13:44