doujiang9887 2014-09-08 09:28
浏览 91
已采纳

使用Golang通道处理HTTP请求

I'm trying to build a simple Golang/Appengine app which uses a channel to handle each http request. Reason is I want each request to perform a reasonable large in- memory calculation, and it's important that each request is performed in a thread- safe manner (ie calculations from concurrent requests don't get mixed).

Essentially I need a synchronous queue which will only process one request at a time, and channels look like a natural fit.

Is it possible to use Go's buffered channel as a thread-safe queue?

However I can't get my simple hello world example to work. It seems to fail on the line 'go process(w, cr)'; I get a 200 response from the server, but no contennt. Works fine if I eliminate 'go' from the this line, but then I'm guessing I'm not calling the channel correctly.

Anyone point out where I'm going wrong ?

Thanks!

// curl -X POST "http://localhost:8080/add" -d "{\"A\":1, \"B\":2}"

package hello

import (
    "encoding/json"
    "net/http"  
)

type MyStruct struct {
    A, B, Total int64
}

func (s *MyStruct) add() {
    s.Total = s.A + s.B
}

func process(w http.ResponseWriter, cr chan *http.Request) {
    r := <- cr
    var s MyStruct
    json.NewDecoder(r.Body).Decode(&s)
    s.add()
    json.NewEncoder(w).Encode(s)
}

func handler(w http.ResponseWriter, r *http.Request) {  
    cr := make(chan *http.Request, 1)
    cr <- r
    go process(w, cr) // doesn't work; no response :-(
    // process(w, cr) // works, but blank response :-(
}

func init() {
    http.HandleFunc("/add", handler)
}
  • 写回答

2条回答 默认 最新

  • dongzhiyi2006 2014-09-08 10:43
    关注

    Not sure this is the right design but I suspect that the issue is that where you're starting the second go routine the first go routine continues and finishes writing the connection etc.

    To stop this you can make the first routine wait using a waitgroup (http://golang.org/pkg/sync/#WaitGroup).

    This stop the whole reasoning behind why you're trying to put this into a thread (hence why I think you've got a design issue).

    Here is some untested code that should work or at least help in the right direction.

    package main
    
    import (
        "encoding/json"
        "net/http"
        "sync"  
    )
    
    type MyStruct struct {
        A, B, Total int64
    }
    
    func (s *MyStruct) add() {
        s.Total = s.A + s.B
    }
    
    func process(w http.ResponseWriter, cr chan *http.Request) {
        r := <- cr
        var s MyStruct
        json.NewDecoder(r.Body).Decode(&s)
        s.add()
        json.NewEncoder(w).Encode(s)
    }
    
    func handler(w http.ResponseWriter, r *http.Request) {  
        cr := make(chan *http.Request, 1)
        cr <- r
        var pleasewait sync.WaitGroup
        pleasewait.Add(1)
    
        go func() {
            defer pleasewait.Done()
            process(w, cr) // doesn't work; no response :-(
        }()
        // process(w, cr) // works, but blank response :-(
    
        pleasewait.Wait()
    }
    
    func main() {
        http.HandleFunc("/add", handler)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?