I experiment a little bit with go http package.
Look at the following code snippet, a very simple http server:
package main
import (
"fmt"
"github.com/codegangsta/negroni"
"github.com/gorilla/mux"
"net/http"
//"time"
)
type controller struct {
request *http.Request
response http.ResponseWriter
}
func (self *controller) send() {
fmt.Fprintf(self.response, "Request %p and Response %p
", self.request, self.response)
}
func (self *controller) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
fmt.Println("Start controller")
self.request = r
self.response = rw
self.send()
}
func main() {
router := mux.NewRouter()
router.Handle("/", &controller{})
n := negroni.Classic()
n.UseHandler(router)
n.Run(":3000")
}
and I make 20 times request to server:
package main
import (
"fmt"
"io"
"net/http"
"runtime"
"time"
)
func main() {
buffer := make([]byte, 100)
runtime.GOMAXPROCS(runtime.NumCPU())
for i := 0; i < 20; i++ {
go func(z int) {
//fmt.Println("Request goroutine 1 ", z)
resp, err := http.Get("http://127.0.0.1:3000")
if err != nil {
fmt.Println(err)
}
io.ReadFull(resp.Body, buffer)
fmt.Println(string(buffer))
}(i)
}
time.Sleep(time.Second * 5)
}
I received the following response:
Request 0xc0820201a0 and Response 0xc082007100
Request 0xc082021380 and Response 0xc0820072c0
Request 0xc0820204e0 and Response 0xc082007740
Request 0xc082020dd0 and Response 0xc0820071c0
Request 0xc082020d00 and Response 0xc082007240
Request 0xc082021450 and Response 0xc082007400
Request 0xc082020f70 and Response 0xc082007500
Request 0xc082021110 and Response 0xc082007480
Request 0xc0820212b0 and Response 0xc082007540
Request 0xc082020b60 and Response 0xc0820075c0
Request 0xc082020750 and Response 0xc082007640
Request 0xc082020270 and Response 0xc0820076c0
Request 0xc082020c30 and Response 0xc082007840
Request 0xc082020820 and Response 0xc0820078c0
Request 0xc082020ea0 and Response 0xc082007940
Request 0xc0820211e0 and Response 0xc0820079c0
Request 0xc082021520 and Response 0xc082007a40
Request 0xc0820209c0 and Response 0xc082007ac0
Request 0xc082021040 and Response 0xc082007380
Request 0xc082020a90 and Response 0xc0820077c0
As you can see here, everything is fine. Every request and response have different storage address.
So if I change the http server to:
package main
import (
"fmt"
"github.com/codegangsta/negroni"
"github.com/gorilla/mux"
"net/http"
"time"
)
type controller struct {
request *http.Request
response http.ResponseWriter
counter int
}
func (self *controller) get() {
self.counter++
if self.counter == 7 {
time.Sleep(time.Second * 4)
}
fmt.Printf("Request %p and Response %p
", self.request, self.response)
}
func (self *controller) send() {
fmt.Fprintf(self.response, "Request %p and Response %p
", self.request, self.response)
}
func (self *controller) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
fmt.Println("Start controller")
self.request = r
self.response = rw
self.get()
self.send()
}
func main() {
router := mux.NewRouter()
router.Handle("/", &controller{})
n := negroni.Classic()
n.UseHandler(router)
n.Run(":3000")
}
As you can see here I've add the method get and when counter reach number 7, it will sleep for 4 second.
func (self *controller) get() {
self.counter++
if self.counter == 7 {
time.Sleep(time.Second * 4)
}
fmt.Printf("Request %p and Response %p
", self.request, self.response)
}
As output I've got
Request 0xc082021040 and Response 0xc082007100
Request 0xc0820209c0 and Response 0xc082007240
Request 0xc0820211e0 and Response 0xc082007380
Request 0xc082020270 and Response 0xc082007500
Request 0xc082020d00 and Response 0xc082007640
Request 0xc082020f70 and Response 0xc082007740
Request 0xc082020680 and Response 0xc082007840
Request 0xc082020820 and Response 0xc082007940
Request 0xc082020b60 and Response 0xc082007a40
Request 0xc082021380 and Response 0xc0820071c0
Request 0xc082021110 and Response 0xc0820072c0
Request 0xc0820208f0 and Response 0xc082007400
Request 0xc082020a90 and Response 0xc082007540
Request 0xc082020340 and Response 0xc0820076c0
Request 0xc082020750 and Response 0xc0820075c0
Request 0xc082020dd0 and Response 0xc0820077c0
Request 0xc0820212b0 and Response 0xc0820078c0
Request 0xc0820201a0 and Response 0xc0820079c0
Request 0xc082020ea0 and Response 0xc082007ac0
Request 0xc082020ea0 and Response 0xc082007ac0
As you can see the address from the last two lines is the same, that means by request 7 the address of request and response will be overwrite, because the response is delay.
My question is, when a request have to process intensive calculation, for example resizing image and during the resizing an other request comes in, the request and response from image resizing process will be overwrite like above. Then the response will go to the last requested client. In my opinion, thats wrong right?
I know that go create for every request a new goroutine.