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 wegame打不开英雄联盟
  • ¥15 公司的电脑,win10系统自带远程协助,访问家里个人电脑,提示出现内部错误,各种常规的设置都已经尝试,感觉公司对此功能进行了限制(我们是集团公司)
  • ¥15 救!ENVI5.6深度学习初始化模型报错怎么办?
  • ¥30 eclipse开启服务后,网页无法打开
  • ¥30 雷达辐射源信号参考模型
  • ¥15 html+css+js如何实现这样子的效果?
  • ¥15 STM32单片机自主设计
  • ¥15 如何在node.js中或者java中给wav格式的音频编码成sil格式呢
  • ¥15 不小心不正规的开发公司导致不给我们y码,
  • ¥15 我的代码无法在vc++中运行呀,错误很多