这个其实不是错误,2个写法没有区别。-2015.11.22

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

在不少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)
}

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

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

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

比如,有个全局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错误的更多相关文章

  1. 开源一个golang小程序商城后台系统(moshopserver)

    开源一个golang小程序商城后台(moshopserver) golang和c/c++比起来是一门新的语言,一直想学,网上搜集了一些资料,有些人说很容易上手,确实是这样,和C/C++比起来,少了很多 ...

  2. 从0写一个Golang日志处理包

    WHY 日志概述 日志几乎是每个实际的软件项目从开发到最后实际运行过程中都必不可少的东西.它对于查看代码运行流程,记录发生的事情等方面都是很重要的. 一个好的日志系统应当能准确地记录需要记录的信息,同 ...

  3. 关于启动 SecureCRT 遇到一个致命的错误且必须关闭

    --------------------------SecureCRT---------------------------SecureCRT 遇到一个致命的错误且必须关闭. 一个崩溃转储文件已创建于 ...

  4. Windows下一个MySQL有些错误的解决方法

    1.无论是什么提示.我们有一个直接看错误日志.由于它描述了最具体描述错误日志. 于MySQL安装文件夹中找到 my.ini简介 看日志保存路径 2. 我的错误是[ERROR] Fatal error: ...

  5. 又是一个愚蠢的错误,皆因.xml而起

       论java中的.xml到底有多坑?! 感觉自己都快哭了,再一次被.xml给坑了一下,这次坑的太狠了,一下子导致自己浪费了昨天一下午,一晚上,今天一上午和半个下午呀,中间的过程真的是乏善可陈呀,各 ...

  6. “SecureCRT遇到一个致命的错误且必须关闭”处理办法

    打开SecureCRT时报错:SecureCRT遇到一个致命的错误且发须关闭.一个崩溃转储文件已创建于... 解决办法是,如下在cmd中输入regedit回车打开注册表编缉器 展开HKEY_LOCAL ...

  7. 推荐一个GOLANG入门很好的网址

    推荐一个GOLANG入门很好的网址,栗子很全 https://books.studygolang.com/gobyexample/

  8. 全局配置一个ajax的错误监控

    全局配置一个ajax的错误监控,比如$(document).ajaxError(function(evt, req, settings){    if(req && (req.stat ...

  9. golang error错误处理

    error定义 数据结构 go语言error是一普通的值,实现方式为简单一个接口. // The error built-in interface type is the conventional i ...

随机推荐

  1. psql工具使用(二)

    所有psql命令都以   \   开头 一.使用psql -l查看有哪些数据库: -bash-4.2$ psql -l List of databases Name | Owner | Encodin ...

  2. LeetCode 169. Majority Element解题方法

    题目: Given an array of size n, find the majority element. The majority element is the element that ap ...

  3. PTA (Advanced Level) 1008 Elevator

    Elevator The highest building in our city has only one elevator. A request list is made up with Npos ...

  4. android 日期控件 DatePicker

    DatePicker的缺陷 提供的API太少,没办法个性化定制.比如,不能指定某部分的颜色,不能控制显示的部分等. xml中提供的属性太少,同样影响定制化. 兼容性问题太多,在4.x,5.x和6.0+ ...

  5. Java并发编程:什么是线程安全,以及并发必须知道的几个概念

    废话 众所周知,在Java的知识体系中,并发编程是非常重要的一环,也是面试的必问题,一个好的Java程序员是必须对并发编程这块有所了解的.为了追求成为一个好的Java程序员,我决定从今天开始死磕Jav ...

  6. 批处理REG学习

    首先在批处理操作注册表之前,应该了解REG命令的使用方式,详情请参阅一下网址: https://www.jb51.net/article/30078.htm 从以上链接内容我们可以详细了解使用reg的 ...

  7. HDU3062(2-SAT)

    Party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  8. Linux 安装redis,redis发布订阅,持久化

    安装redis 1.安装redis的方式 -yum (删除这个yum安装的redis,我们只用源码编译安装的) -rpm -源码编译 2.删除原本的redis yum remove redis -y ...

  9. python的深浅拷贝以及fromkeys的用法

    1.join()的用法:使用前面的字符串.对后面的列表进行拼接,拼接结果是一个字符串 # lst = ["alex","dsb",'wusir','xsb'] ...

  10. JAVA中销毁session的代码

    ServletActionContext.getRequest().getSession().invalidate();