我相信和很多使用golang的朋友一样,开始接触并学习go语言都是被其优秀的并发能力所吸引。比如我需要从一个目录中,筛选符合要求的(比如时间符合)日志,然后从其中提取一些数据。就可以以下面的方式:

package main
import (
    "fmt"
    "time"
)

func worker(task_id int, filepath string, w io.Writer) {
    ... 处理 filepath 的文件
    ... 将处理结果写入w中(golang中高度抽象的io.Writer 和io.Reader非常便于将)
    // 或将结果传入管道 ch <- fmt.Sprintf("%d,%s", task_id, res)
}
func main() {
    input := [...]string{}
    start := time.Now()
    ... 获取某个目录下的所有文件,然后做合法性判断,并将它们存入上面的数组中
    for i, filepath := range input {
        go worker(i, filepath, w)
}
    // 或创建一个管道 chan := make(chan string)
    // 将处理结果在worker 中传入管道,然后在这里遍历管道取出
    // for range chan_name { fmt.Println(<- ch) }
    end := time.Now()
    fmt.Printf("Job Finished,Spent %s Secs On Processing", end.Sub(start))
}

golang中的管道,就是用于go协程之间的内存共享的具体实现。这样就完成了一个最基础的并发应用。我之前是使用pypy运行python脚本完成相同的工作,几十个日志文件也需要耗费若干分钟的时间。而使用golang,只需要花费数十秒。

当然这样实现是不妥当的,这样会同时创建若干个go协程,同时开始工作。而由于go语言本身设置,如果不在代码中设置使用的cpu数量,那么就会利用所有核心,瞬间导致系统IO负载暴增。并且,如果我们有这样的需求——要求任务结果能按照任务传入管道的顺序输出。那么目前这种代码显然是无法满足我们的需求的。