在 Golang 中使用 Go 關鍵字和 Channel 實現並行

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

Go 關鍵字和 channel 的用法

go 關鍵字用來建立 goroutine (協程),是實現並發的關鍵。go 關鍵字的用法如下:
//go 關鍵字放在方法調用前建立一個 goroutine 並讓他執行方法體go GetThingDone(param1, param2);//上例的變種,建立一個匿名方法並執行go func(param1, param2) {}(val1, val2)//直接建立一個 goroutine 並在 goroutine 中執行代碼塊go {    //do someting...}
因為 goroutine 在多核 cpu 環境下是並行的。如果代碼塊在多個 goroutine 中執行,我們就實現了代碼並行。那麼問題來了,怎麼拿到並行的結果呢?這就得用 channel 了。
//resultChan 是一個 int 類型的 channel。類似一個信封,裡面放的是 int 類型的值。var resultChan chan int//將 123 放到這個信封裡面,供別人從信封中取用resultChan <- 123//從 resultChan 中取值。這個時候 result := 123result := <- resultChan

使用 go 關鍵字和 channel 實現非阻塞調用

阻塞的意思是調用方在被調用的代碼返回之前必須一直等待,不能處理別的事情。而非阻塞調用則不用等待,調用之後立刻返回。那麼傳回值如何擷取呢?Node.js 使用的是回調的方式,Golang 使用的是 channel。
/** * 每次調用方法會建立一個 channel : resultChan, * 同時建立一個 goroutine 來發起 http 請求並擷取結果。 * 擷取到結果之後 goroutine 會將結果寫入到 resultChan。 */func UnblockGet(requestUrl string) chan string {    resultChan := make(chan string)    go func() {        request := httplib.Get(requestUrl)        content, err := request.String()        if err != nil {            content = "" + err.Error()        }        resultChan <- content    } ()    return resultChan}

由於建立的 goroutine 不會阻塞函數主流程的執行,所以調用 UnblockGet 方法會立刻得到一個 resultChan 傳回值。一旦 goroutine 執行完畢拿到結果就會寫入到 resultChan 中,這時外部就可以從 resultChan 中擷取執行結果。

一個很 low 的並行樣本

fmt.Println(time.Now())resultChan1 := UnblockGet("http://127.0.0.1/test.php?i=1")resultChan2 := UnblockGet("http://127.0.0.1/test.php?i=2")fmt.Println(<-resultChan1)fmt.Println(<-resultChan1)fmt.Println(time.Now())

上面兩個 http 請求是在兩個 goroutine 中並行的。總的執行時間小於 兩個請求時間和。

這個例子只是為了體現 go 和 channel 的用法,有記憶體流失問題,千萬不要線上上這麼搞。因為建立的 channel 沒有 close。下次寫一個更進階一點的。

簡單的實現 http multi GET

type RemoteResult struct {    Url string    Result string}func RemoteGet(requestUrl string, resultChan chan RemoteResult)  {    request := httplib.NewBeegoRequest(requestUrl, "GET")    request.SetTimeout(2 * time.Second, 5 * time.Second)    //request.String()    content, err := request.String()    if err != nil {        content = "" + err.Error()    }    resultChan <- RemoteResult{Url:requestUrl, Result:content}}func MultiGet(urls []string) []RemoteResult {    fmt.Println(time.Now())    resultChan := make(chan RemoteResult, len(urls))    defer close(resultChan)    var result []RemoteResult    //fmt.Println(result)    for _, url := range urls {        go RemoteGet(url, resultChan)    }    for i:= 0; i < len(urls); i++ {        res := <-resultChan        result = append(result, res)    }    fmt.Println(time.Now())    return result}func main() {    urls := []string{        "http://127.0.0.1/test.php?i=13",        "http://127.0.0.1/test.php?i=14",        "http://127.0.0.1/test.php?i=15",        "http://127.0.0.1/test.php?i=16",        "http://127.0.0.1/test.php?i=17",        "http://127.0.0.1/test.php?i=18",        "http://127.0.0.1/test.php?i=19",        "http://127.0.0.1/test.php?i=20"    }    content := MultiGet(urls)    fmt.Println(content)}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.