golang net/http的小問題?
我用golang(1.7.3)的net/http庫開發了一個簡單的http server
一個簡單的handler如下,正常工作:
func serve(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "serve")
}
但是改為新開一個goroutine處理這個請求後,發現http 連接會被提前關閉:
func serve(w http.ResponseWriter, r *http.Request) {
go func(){
io.WriteString(w, "serve")
}()
}
感覺就是這個http.ResponseWriter在函數間傳遞多次都沒問題,但是一切換goroutine就會被關閉,這個怎麼辦呢?是為什麼?
Go 仍然是一門必須隨時翻 ref/spec 和源碼才能寫代碼的語言……文檔本身是完全不夠的……
https://golang.org/src/net/http/server.go?s=51112:51172#L1574
// HTTP cannot have multiple simultaneous active requests.[*]
// Until the server replies to this request, it can"t read another,
// so we might as well run the handler in this goroutine.
// [*] Not strictly true: HTTP pipelining. We could let them all process
// in parallel even if their responses need to be serialized.
serverHandler{c.server}.ServeHTTP(w, w.req)
w.cancelCtx()
2、如上面代碼所示,net/http 框架期待 handler 是同步執行的。「提前關閉」就是 w.cancelCtx 做的,因為它認為 handler 已經執行完了。
http本身就是基於goroutine實現,沒有必要這麼寫。
文檔說的很清楚,handler退出即認為處理結束
哥們兒 你知道文檔是幹啥的不
是對goroutine 沒有理解,通過goroutine 執行我更願意理解為委託,是將一個函數委託給一個goroutine,而委託函數不會對委託者進行block,有很多類似goroutine 例子,表現狀態都是委託者函數執行完畢而委託函數才剛剛開始,代碼增加chan 就可以解決,其實本質就是等待委託函數執行完畢,所有的非同步編程都是一樣,和語言無關,你只是缺少一個callback罷了。
頂唐生的說法
樓主可以看一下martini的源碼,應該跟golang原有的差不多思路。 for r.index &< len(r.handlers) {
handler := r.handlers[r.index]
vals, err := r.Invoke(handler)
if err != nil {
panic(err)
}
r.index += 1
//some function
if r.Written() {
return
}
}
問題的關鍵在於當這一批處理函數執行完或者進行了w.Write這一操作,則r.Written()會為true了,不會繼續往下走了。當你起了goroutine之後並退出serve函數之後,被認為整個流程已經走完,http連接已經處於idle的狀態,這是不允許在對req進行處理了
我們項目的代碼通常會在http處理流程中使用goroutine進行統計
推薦閱讀:
※想寫個web伺服器,用Go語言實現,需要有哪些前提知識呢?
※怎麼在Linux操作系統搭建HTTP伺服器?
※這種情況下,304還是200更好?
※HTTP冪等性概念?
※WebSocket 是什麼原理?為什麼可以實現持久連接?