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条)

报告相同问题?

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器