很多数据竞赛的Web应用程序

I am writing a web application. Incoming requests will pass through middlewares first. At the moment, I've added two middlwares session and security.
After walked through middlwares, it will execute the handler for the request. Session and security middlwares will execute in their own goroutine.

When I am testing I've got a lot of data race, specially in middlware section

WARNING: DATA RACE
Write by goroutine 18:
  runtime.mapassign1()
      c:/go/src/runtime/hashmap.go:383 +0x0
  net/textproto.MIMEHeader.Set()
      c:/go/src/net/textproto/header.go:22 +0xf4
  net/http.Header.Set()
      c:/go/src/net/http/header.go:31 +0x64
  project/middlewares/session.(*ctrl).setHttpHeader()
      D:/gocode/src/project/middlewares/session/ctrl.go:76 +0x9d
  project/middlewares/session.(*ctrl).evaluateJwt()
      D:/gocode/src/project/middlewares/session/ctrl.go:56 +0x31a
  project/middlewares/session.(*ctrl).serveHttp()
      D:/gocode/src/project/middlewares/session/ctrl.go:94 +0x8a
  project/middlewares/session.func┬À006()
      D:/gocode/src/project/middlewares/session/serve_http.go:23 +0x

Previous write by goroutine 17:
  runtime.mapassign1()
      c:/go/src/runtime/hashmap.go:383 +0x0
  net/textproto.MIMEHeader.Add()
      c:/go/src/net/textproto/header.go:15 +0x212
  net/http.Header.Add()
      c:/go/src/net/http/header.go:24 +0x64
  github.com/unrolled/secure.(*Secure).Process()
      D:/gocode/src/github.com/unrolled/secure/secure.go:177 +0xe5b
  project/middlewares/security.func┬À001()
      D:/gocode/src/project/middlewares/security/serve_http.go:33 +0

Goroutine 18 (running) created at:
  project/middlewares/session.ServeHttp()
      D:/gocode/src/project/middlewares/session/serve_http.go:29 +0x
  project/middlewares.New()
      D:/gocode/src/project/middlewares/ctrl.go:12 +0x99
  github.com/codegangsta/negroni.HandlerFunc.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:24 +0x5f
  github.com/codegangsta/negroni.middleware.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x114
  github.com/codegangsta/negroni.middleware.ServeHTTP┬Àfm()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x84
  github.com/codegangsta/negroni.(*Static).ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/static.go:30 +0xb71
  github.com/codegangsta/negroni.middleware.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x114
  github.com/codegangsta/negroni.middleware.ServeHTTP┬Àfm()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x84
  github.com/codegangsta/negroni.(*Logger).ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/logger.go:25 +0x249
  github.com/codegangsta/negroni.middleware.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x114
  github.com/codegangsta/negroni.middleware.ServeHTTP┬Àfm()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x84
  github.com/codegangsta/negroni.(*Recovery).ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/recovery.go:45 +0xd9
  github.com/codegangsta/negroni.middleware.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x114
  github.com/codegangsta/negroni.(*Negroni).ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:73 +0x1c7
  net/http/httptest.(*waitGroupHandler).ServeHTTP()
      c:/go/src/net/http/httptest/server.go:200 +0xfe
  net/http.serverHandler.ServeHTTP()
      c:/go/src/net/http/server.go:1703 +0x1fd
  net/http.(*conn).serve()
      c:/go/src/net/http/server.go:1204 +0x108e

Goroutine 17 (finished) created at:
  project/middlewares/security.ServeHttp()
      D:/gocode/src/project/middlewares/security/serve_http.go:37 +0
  project/middlewares.New()
      D:/gocode/src/project/middlewares/ctrl.go:12 +0x64
  github.com/codegangsta/negroni.HandlerFunc.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:24 +0x5f
  github.com/codegangsta/negroni.middleware.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x114
  github.com/codegangsta/negroni.middleware.ServeHTTP┬Àfm()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x84
  github.com/codegangsta/negroni.(*Static).ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/static.go:30 +0xb71
  github.com/codegangsta/negroni.middleware.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x114
  github.com/codegangsta/negroni.middleware.ServeHTTP┬Àfm()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x84
  github.com/codegangsta/negroni.(*Logger).ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/logger.go:25 +0x249
  github.com/codegangsta/negroni.middleware.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x114
  github.com/codegangsta/negroni.middleware.ServeHTTP┬Àfm()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x84
  github.com/codegangsta/negroni.(*Recovery).ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/recovery.go:45 +0xd9
  github.com/codegangsta/negroni.middleware.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x114
  github.com/codegangsta/negroni.(*Negroni).ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:73 +0x1c7
  net/http/httptest.(*waitGroupHandler).ServeHTTP()
      c:/go/src/net/http/httptest/server.go:200 +0xfe
  net/http.serverHandler.ServeHTTP()
      c:/go/src/net/http/server.go:1703 +0x1fd
  net/http.(*conn).serve()
      c:/go/src/net/http/server.go:1204 +0x108e
==================
2015/02/03 15:05:31 ctrl.go:17: End of process middlewares
2015/02/03 15:05:31 funcs.go:10: Create new user
2015/02/03 15:05:31 validate.go:14: Validate email thompson@example.com
2015/02/03 15:05:31 validate.go:100: Validate password Test!1234
2015/02/03 15:05:31 validate.go:52: Validate name:  ValidName
2015/02/03 15:05:31 create.go:120: Done
[negroni] Completed 0  in 197ms
PASS
ok      project/testing/account_test 0.664s
PS D:\gocode\src\project\testing\account_test> go test -race
2015/02/03 15:08:10 vs.go:50: Connect to neo4j db.
[negroni] Started POST /user
==================
WARNING: DATA RACE
Write by goroutine 18:
  net/http.(*response).Header()
      c:/go/src/net/http/server.go:615 +0x11a
  github.com/codegangsta/negroni.(*responseWriter).Header()
      <autogenerated>:42 +0x78
  project/middlewares/session.(*ctrl).setHttpHeader()
      D:/gocode/src/project/middlewares/session/ctrl.go:76 +0x68
  project/middlewares/session.(*ctrl).evaluateJwt()
      D:/gocode/src/project/middlewares/session/ctrl.go:56 +0x31a
  project/middlewares/session.(*ctrl).serveHttp()
      D:/gocode/src/project/middlewares/session/ctrl.go:94 +0x8a
  project/middlewares/session.func┬À006()
      D:/gocode/src/project/middlewares/session/serve_http.go:23 +0x

Previous write by goroutine 17:
  net/http.(*response).Header()
      c:/go/src/net/http/server.go:615 +0x11a
  github.com/codegangsta/negroni.(*responseWriter).Header()
      <autogenerated>:42 +0x78
  github.com/unrolled/secure.(*Secure).Process()
      D:/gocode/src/github.com/unrolled/secure/secure.go:177 +0xe24
  project/middlewares/security.func┬À001()
      D:/gocode/src/project/middlewares/security/serve_http.go:33 +0

I use negroni to process middlwares works.

The way, how I process middlwares

func New(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) {

    if err := process(security.ServeHttp(res, req), session.ServeHttp(res, req)); err != nil {
        res.WriteHeader(http.StatusInternalServerError)
        return
    }

    log.Println("End of process middlewares")
    next(res, req)

}

// Process all middlewares
func process(chErrs ...<-chan error) error {

    for _, chErr := range chErrs {

        // Will abort the loop, when error occurs
        if err := <-chErr; err != nil {
            return err
        }

    }
    return nil
}

As you can see, every middlware have they own channel. The for statement will loop until the error channel is closed or error send.

The server configuration

func Config() *negroni.Negroni {
    n := negroni.Classic()
    n.Use(negroni.HandlerFunc(middlewares.New))
    n.UseHandler(routes.Set())
    return n

}

My question is, are the middlewares the reason, why I've got the data race?

It's the fact that you're running the middleware within a goroutine that is the problem.

If you want to run your middleware in parallel you will have to set up a mutex around the memory that is written to by any middleware executed within a goroutine.

In your particular case you are both writing and reading from the ResponseWriter's Header