這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
最近有小夥伴碰到了問了下面的問題。
handler拿到一個請求,然後把請求放到一個channel裡面,一個gorutine一直在從這個channel取值做處理。如果我想在handler裡面返回處理結果,是不是現在的流程無法實現呢?
他這樣問我,因為自己是菜雞無法回答,我打算自己嘗試一下
首先搭了一些個簡單的http伺服器
func main(){http.HandleFunc("/", handler)http.ListenAndServe("localhost:8082", nil)}
然後將goroutine和channel跑起來
func Test (){ch := make(chan int, 1)sign := make(chan byte, 2)go func() {for i := 0; i < 5; i++ {ch <- itime.Sleep(1 * time.Second)}close(ch)fmt.Println("The channel is closed.")sign <- 0}()go func() {//這個迴圈會一直嘗試從ch中讀取資訊出來 即使ch已經被發送端關閉//但還是可以讀資訊出來 最後當ok 為false的時候 說明已經沒有資料從ch中讀出//跳出迴圈 注意這種判斷方式for {fmt.Printf("before extract channel len: %v ,", len(ch))e, ok := <-chfmt.Printf("channel value: %d if extract ok :(%v) after extraction channel len : %v channel cap : %v \n", e, ok, len(ch), cap(ch))if !ok {break}time.Sleep(2 * time.Second)}fmt.Println("Done.")sign <- 1}()//要是不添加兩次取值的操作的話 主進程就會馬上結束 這裡相當於是實現了一個//同步的操作 等待兩個go func都結束之後 再結束主進程 注意這種技巧<-sign<-sign}
基本無問題,然後對這個代碼進行了改造,然後得到了如下的代碼
結構體
type HandlerDemo struct {writer http.ResponseWriterrequest *http.Request}
具體實現代碼
func handler(w http.ResponseWriter, r *http.Request) {fmt.Println("start...")//test response/*w.WriteHeader(http.StatusOK) // 200fmt.Fprintf(w, "this msg: %v\n", 123)return*/info:=HandlerDemo{}info.writer=winfo.request=rresult:=HandlerDemo{}ch := make(chan HandlerDemo, 1)ch <- infoclose(ch)fmt.Println("ch is have data..")go func() {fmt.Println("start run goroutine..")fmt.Println("try get ch val..")e, ok := <-chfmt.Printf("channel value: %d if extract ok :(%v) after extraction channel len : %v channel cap : %v \n", e, ok, len(ch), cap(ch))if ok{result.writer=e.writerresult.request=e.requestfmt.Printf("result value: %d \n", result)}}()time.Sleep(3 * time.Second)fmt.Println("over...")fmt.Println("this val is get and try response..")result.writer.WriteHeader(http.StatusOK)fmt.Fprintf(result.writer,"this response msg: %v\n", "hello")return}
可以看到,我卡了很久在這使用了Sleep才成功將資訊返回。http輸入必然輸出,開啟goroutine時相當於非同步,通訊還是會繼續下去直到結束,它會先返回空值,在goroutine裡返回會報錯多次返回,於是我採用極端的方法做到了返回,拿到了久違的hello。但是這種方法顯然不適合應用,改進方法將睡眠時間改為判斷goroutine結束,這樣就更加合理一些!!哈哈哈
314 次點擊 ∙ 1 贊