go的協程及channel與web開發的一點小實踐
前言
之前在網上看go的協程和channel的東西,感覺都是一個main方法闖天下,並沒有很好的體會到channel的美妙,然後自己花了點時間寫了一點簡單的demo,然後不斷的變換,去看效果和輸出。
思路
我用channel去實現產生累積的web請求,然後用sleep去休眠消費者協程造成處理業務場景的假象,然後開多個消費者協程去處理web請求。
程式碼
package main
import (
"fmt"
"log"
"net/http"
"strings"
"time"
)
//實際的業務處理
func sayhelloName(w http.ResponseWriter, r *http.Request) {
param := r.URL.Query()
id := param.Get("id")
idArr := strings.Split(id,",")
//呼叫生產者
go produceIdToChannel(idArr)
//由於消費者用了sleep去休眠造成處理業務的假象,所以這裡用多協程的方式去處理,大家可以試著取消迴圈來起多個執行緒的方法,就用一個執行緒來跑,看看花費的時間是多少?
for i:=0;i<len(idArr);i++{
go consumIdFromChannel()
}
fmt.Fprintf(w, "Hello first webchannel!") //這個寫入到w的是輸出到客戶端的
}
func main() {
http.HandleFunc("/", sayhelloName) //設定訪問的路由
err := http.ListenAndServe(":9090", nil) //設定監聽的埠
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
//宣告一個channel模擬佇列,如果這裡用一個緩衝的chan呢,看看話費的時間又是多少呢?
var picIdChannel chan string = make(chan string)
func produceIdToChannel(id []string){
t := time.Now()
for i:=0;i<len(id);i++ {
picIdChannel <- id[i]
fmt.Println("生產picId",id[i])
}
fmt.Println("花費時間",time.Since(t))
}
func consumIdFromChannel(){
for{
time.Sleep(time.Second * 10)
e,_ := <-picIdChannel
fmt.Println("消費picId",e)
}
}
web請求
http://localhost:9090/sayhelloName?id=1,2,3,4,5,6,7,8,9,10
會發現迴圈來起多個執行緒的方法話費的時間
花費時間 10.011475s
假如去掉迴圈就一個協程來跑話費的時間
花費時間 60.0036594s
這就是起多個協程的威力,多個協程分別處理掉了每個業務裡面接收通道值之前的業務(在這裡為模擬的 time.Sleep(time.Second * 10)
),後面通道釋放立馬跟上處理通道資料即可!
如果是改為緩衝的chan,會發現花費時間為0,這就很好理解為什麼不緩衝的chan是阻塞的,消費掉當前的訊息下一個訊息才會進來!
如果多次連續請求這個url,會依次累積處理。
大家和還可以自己隨心改動,自己去體驗思考這樣才會對channel和協程有更清晰的認識!
問題
其實我這裡也有一些問題,比如消費者開一個for迴圈來處理chan裡面的值是否合適?有沒有更好的解決方法?select在我這個demo裡怎麼用最合適?協程的數量一般多少為好?
應該還有很多問題我沒想到的,希望後面的學習實踐中這些問題都會有答案,也希望有大佬給我指正答疑。
相關文章
- Go實戰-基於Go協程和channel的使用Go
- Swoole協程與Go協程的區別Go
- Swoole 協程與 Go 協程的區別Go
- python 協程與go協程的區別PythonGo
- GO 語言 Web 開發實戰一GoWeb
- 開源實踐 | 攜程在OceanBase的探索與實踐
- 開源實踐 | 攜程在 OceanBase 的探索與實踐
- 協程在RN中的實踐
- Java服務端開發非同步化實踐的一點小結Java服務端非同步
- Go 併發 -- 協程Go
- 《微信小程式開發 入門與實踐》知識點整理微信小程式
- go 技巧: 實現一個無限 buffer 的 channelGo
- 技術實踐——教你用100行寫一個 go 的協程池 (任務池)!!!Go
- DDS協議解讀及測試開發實踐協議
- puppeteer在開發過程中的實踐
- Go 中的 channel 怎麼實現的?Go
- 小程式開發總結一:mpvue框架及與小程式原生的混搭開發Vue框架
- go lang學習筆記——channel機理及排程理解Go筆記
- go併發 - channelGo
- Golang —— goroutine(協程)和channel(管道)Golang
- Go channel 的妙用Go
- 理解 Go 中的協程(Goroutine)Go
- 使用 Go Channel 及 Goroutine 時機Go
- Flutter外掛開發指南01: 通道Channel的編寫與實現Flutter
- 一小時完成後臺開發:DjangoRestFramework開發實踐DjangoRESTFramework
- iOS BLE 開發小記[5] 與 Remote Peripheral 互動的最佳實踐iOSREM
- go web開發(gin&gorm) 之DB配置及DAO的基本使用GoWebORM
- Go 中的 channel 與 Java BlockingQueue 的本質區別GoJavaBloC
- 一個web前端開發者學習Flutter 的歷程(一)Web前端Flutter
- Python協程與JavaScript協程的對比PythonJavaScript
- 微信小程式開發的一點心得微信小程式
- Android版kotlin協程入門(四):kotlin協程開發實戰AndroidKotlin
- Go channel 實現原理分析Go
- 使用 Mpvue 開發微信小程式的最佳實踐Vue微信小程式
- 在 Android 開發中使用 Kotlin 協程 (一) -- 初識 Kotlin 協程AndroidKotlin
- 小程式開發實踐總結
- 盤點Go中的開發神器Go
- web開發安全之請求及返回流資料加解密實踐Web解密