首页 > 代码库 > 个人犯的一个golang routine错误

个人犯的一个golang routine错误

认识golang也不少时间了,也做过几个项目。最近发现之前用golang写的一个服务,内存涨得比较快,一直没找出来原因来。今天把疑惑发到群里,经过golang学习班的童鞋的指点,发现我一个常用的错误。

 

在不少golang入门的文章上,用并发的例子一般是这样写的;

package mainimport (    "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)}

我之前的项目,也一直是这样写。今天和群里的讨论了下,才发觉,这个写法其实是比较丑陋的。

其实可以通过这个去实现。

package mainimport (    "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来处理每个用户请求。

比如,有个全局Map变量: map[int]list,  每个请求创建一个巍峨唯一的随机数或者sessionId, 然后每个go rouine处理完后,根据sessionid去查找对应的list, 插入数据。

可以利用list来实现异步队列的机制,避免锁。

所以特地在这记录下来,当然各位新人的参考。

 

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

个人犯的一个golang routine错误