我正在尝试构建一个简单的Golang / Appengine应用程序,该应用程序使用通道来处理每个http请求。原因是我希望每个请求都执行合理的大内存计算,并且以线程安全的方式执行每个请求(即,并发请求的计算不会混淆)非常重要。
本质上,我需要一个同步队列,该队列一次只能处理一个请求,并且通道看起来很自然。
是否可以将Go的缓冲通道用作线程安全队列?
但是,我无法让我简单的hello world示例起作用。似乎在’goprocess(w,cr)’行上失败了;我从服务器收到200响应,但没有竞争。如果我在此行中消除了“ go”,则效果很好,但是我猜我没有正确调用该通道。
有人指出我要去哪里了吗?
谢谢!
// 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) }
不确定这是否是正确的设计,但我怀疑问题是在您启动第二个go例程的地方,第一个go例程继续并完成了写入连接等操作。
要停止此操作,您可以使用等待组(http://golang.org/pkg/sync/#WaitGroup)使第一个例程等待。
这阻止了您试图将其放入线程的全部理由(因此,我认为您遇到了设计问题)。
这是一些未经测试的代码,应该可以正常工作,或者至少在正确的方向上有所帮助。
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) }