標籤:

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

1、Accept 在調用用戶 handler 之前已經啟了 goroutine,所以沒必要啟。

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 是什麼原理?為什麼可以實現持久連接?

TAG:HTTP | Go語言 |