我的犯的一個golang routine錯誤

這個其實不是錯誤,2個寫法沒有區別。-2015.11.22golang

 

認識golang也很多時間了,也作過幾個項目。最近發現以前用golang寫的一個服務,內存漲得比較快,一直沒找出來緣由來。今天把疑惑發到羣裏,通過golang學習班的童鞋的指點,發現我一個經常使用的錯誤。json

 

在很多golang入門的文章上,用併發的例子通常是這樣寫的;服務器

package main

import (
    "fmt"
    "time" ) func main() { messages := make(chan int) go func() { time.Sleep(time.Second * 3) messages <- 1 }() go func() { time.Sleep(time.Second * 2) messages <- 2 }() go func() { time.Sleep(time.Second * 1) messages <- 3 }() go func() { for i := range messages { fmt.Println(i) } }() time.Sleep(time.Second * 5) }

我以前的項目,也一直是這樣寫。今天和羣裏的討論了下,才發覺,這個寫法實際上是比較醜陋的。session

其實能夠經過這個去實現。併發

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "sync" ) func main() { urls := []string{ "http://www.reddit.com/r/aww.json", "http://www.reddit.com/r/funny.json", "http://www.reddit.com/r/programming.json", } jsonResponses := make(chan string) var wg sync.WaitGroup wg.Add(len(urls)) for _, url := range urls { go func(url string) { defer wg.Done() res, err := http.Get(url) if err != nil { log.Fatal(err) } else { defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { log.Fatal(err) } else { jsonResponses <- string(body) } } }(url) } go func() { for response := range jsonResponses { fmt.Println(response) } }() wg.Wait() }

 

這個更簡單,並且也更方便使用。性能方面,應該比chan要好點。異步

我以前的一個案例是,client發一個http request過來, 服務器收到請求,而後同時開N個go routine去處理,而後每一個處理完成後,經過chan 進行傳遞給主線程,主線程判斷chan的是否接收完成全部的請求,而後再響應。性能

就是用的第一種方法。學習

今天根據羣裏面體的建議,重構了下。使用list來處理每一個用戶請求。ui

好比,有個全局Map變量: map[int]list,  每一個請求建立一個巍峨惟一的隨機數或者sessionId, 而後每一個go rouine處理完後,根據sessionid去查找對應的list, 插入數據。url

能夠利用list來實現異步隊列的機制,避免鎖。

因此特意在這記錄下來,固然各位新人的參考。

 

附上國外的一篇文章:  http://nathanleclaire.com/blog/2014/02/15/how-to-wait-for-all-goroutines-to-finish-executing-before-continuing/

相關文章
相關標籤/搜索