I am playing around with Go a bit and I've a problem that I am unable to solve.
The following code is the least possible code that reproduces my problem. The goal of the original code is to delegate http request to goroutines. Each goroutine does a bit of heavy image calculations and is supposed to respond.
package main
import (
"fmt"
"runtime"
"net/http"
)
func main() {
http.HandleFunc("/", handle)
http.ListenAndServe(":8080", nil)
}
func handle(w http.ResponseWriter, r *http.Request) {
// the idea is to be able to handle several requests
// in parallel
// the "go" is problematic
go delegate(w)
}
func delegate(w http.ResponseWriter) {
// do some heavy calculations first
// present the result (in the original code, the image)
fmt.Fprint(w, "hello")
}
In the case of a go delegate(w)
I get no response, without the go
it
works out nicely.
Can anyone explain what's going on? Thanks a lot!
ListenAndServe
already launches goroutines to call your handler function, so you shouldn't do it yourself.
Here's the code of the relevant functions from the package source :
1089 func ListenAndServe(addr string, handler Handler) error {
1090 server := &Server{Addr: addr, Handler: handler}
1091 return server.ListenAndServe()
1092 }
1010 func (srv *Server) ListenAndServe() error {
1011 addr := srv.Addr
1012 if addr == "" {
1013 addr = ":http"
1014 }
1015 l, e := net.Listen("tcp", addr)
1016 if e != nil {
1017 return e
1018 }
1019 return srv.Serve(l)
1020 }
1025 func (srv *Server) Serve(l net.Listener) error {
1026 defer l.Close()
1027 var tempDelay time.Duration // how long to sleep on accept failure
1028 for {
1057 go c.serve()
1058 }
1059 panic("not reached")
1060 }
579 // Serve a new connection.
580 func (c *conn) serve() {
581 defer func() {
582 err := recover()
669 handler.ServeHTTP(w, w.req)
So your code should simply be
func handle(w http.ResponseWriter, r *http.Request) {
// the idea is to be able to handle several requests
// in parallel
// do some heavy calculations first
// present the result (in the original code, the image)
fmt.Fprint(w, "hello")
}
The handler is already called from an "outer" goroutine (a per request one). The handler must do everything what has to be done, e.g. writing a full response, before it returns. You're returning "prematurely" b/c of a superfluous go statement. Please try simply to put the body of "delegate" in 'handle' and check if that improves something ;-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With