我相信和很多使用golang的朋友一樣,開(kāi)始接觸并學(xué)習(xí)go語(yǔ)言都是被其優(yōu)秀的并發(fā)能力所吸引。比如我需要從一個(gè)目錄中,篩選符合要求的(比如時(shí)間符合)日志,然后從其中提取一些數(shù)據(jù)。就可以以下面的方式:
package main
import (
"fmt"
"time"
)
func worker(task_id int, filepath string, w io.Writer) {
... 處理 filepath 的文件
... 將處理結(jié)果寫(xiě)入w中(golang中高度抽象的io.Writer 和io.Reader非常便于將)
// 或?qū)⒔Y(jié)果傳入管道 ch <- fmt.Sprintf("%d,%s", task_id, res)
}
func main() {
input := [...]string{}
start := time.Now()
... 獲取某個(gè)目錄下的所有文件,然后做合法性判斷,并將它們存入上面的數(shù)組中
for i, filepath := range input {
go worker(i, filepath, w)
}
// 或創(chuàng)建一個(gè)管道 chan := make(chan string)
// 將處理結(jié)果在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協(xié)程之間的內(nèi)存共享的具體實(shí)現(xiàn)。這樣就完成了一個(gè)最基礎(chǔ)的并發(fā)應(yīng)用。我之前是使用pypy運(yùn)行python腳本完成相同的工作,幾十個(gè)日志文件也需要耗費(fèi)若干分鐘的時(shí)間。而使用golang,只需要花費(fèi)數(shù)十秒。
當(dāng)然這樣實(shí)現(xiàn)是不妥當(dāng)?shù)?,這樣會(huì)同時(shí)創(chuàng)建若干個(gè)go協(xié)程,同時(shí)開(kāi)始工作。而由于go語(yǔ)言本身設(shè)置,如果不在代碼中設(shè)置使用的cpu數(shù)量,那么就會(huì)利用所有核心,瞬間導(dǎo)致系統(tǒng)IO負(fù)載暴增。并且,如果我們有這樣的需求——要求任務(wù)結(jié)果能按照任務(wù)傳入管道的順序輸出。那么目前這種代碼顯然是無(wú)法滿(mǎn)足我們的需求的。