理解 Go 中的協程(Goroutine)

kuibatian發表於2020-03-05

理解Go中的協程(Goroutine)

前面講的都是一些Go 語言的基礎知識,感興趣的朋友可以先看看之前的文章。https://www.cnblogs.com/zhangweizhong/cate...

今天就來講講go 裡面的高階功能,也是go語言重要的特性:Go協程(Goroutine)。

Go協程(Goroutine)是與其他函式同時執行的函式。可以認為Go協程是輕量級的執行緒,由Go執行時來管理。

在函式呼叫前加上go關鍵字,這次呼叫就會在一個新的goroutine中併發執行。當被呼叫的函式返回時,這個goroutine也自動結束。聽著感覺像C# 中的Task。

需要注意的是,如果這個函式有返回值,那麼這個返回值會被丟棄。

Go 協程(Goroutine)之間通過通道(channel)進行通訊,簡單的說就是多個協程之間通訊的管道。通道可以防止多個協程訪問共享記憶體時發生資源爭搶的問題。


package main

import ( "fmt"
    "time" )

func hello() {  
    fmt.Println("Hello world goroutine")
}
func main() {  
    go hello()
    time.Sleep(1 * time.Second)
    fmt.Println("main function")
}

Channel(管道) 可以被認為是協程之間通訊的管道。與水流從管道的一端流向另一端一樣,資料可以從通道的一端傳送並在另一端接收。

1. 定義

每個channel都有一個型別。此型別是允許通道傳輸的資料型別。channel是型別相關的,一個channel只能傳遞一種型別的值,這個型別需要在宣告channel時指定。

2. 宣告

a. 我們需要通過內建函式 make 來建立一個通道。

下面的程式碼宣告瞭一個通道:

var ch chan int

b. 與其他變數定義一樣,快速宣告也是定義通道的一種有效而簡潔的方式:

a := make(chan int) 

c. 建立一個帶緩衝的channel

c := make(chan int, 1024) // 從帶緩衝的channel中讀資料
for i:=range c {
  ...
}

3. 傳送和接收資料

通過通道傳送和接收資料的語法如下:

data := <- a   // 從channel a 讀取資料 
a <- data      // 將資料寫入到 channel a 

箭頭的指向說明了資料是傳送還是接收。

下面就直接說說,Goroutine和channel 共同使用的完整例子:


package main

import ( "fmt"
    "time" )

func Producer(queue chan<- int) { for i := 0; i < 10; i++ {
        queue <- i //寫入
        fmt.Println("create :", i)
    }
}

func Consumer(queue <-chan int) { for i := 0; i < 10; i++ {
        v := <-queue  // 讀出
        fmt.Println("receive:", v)
    }
}

func main() {
    queue := make(chan int, 88)
    go Producer(queue)
    go Consumer(queue)
    time.Sleep(1 * time.Second)
}

以上,就簡單的介紹了Go語言中的協程(Goroutine)和通道(channel)。這兩個功能特性,是go語言中重要的特性。大家可以寫寫其他的例子,熟悉掌握。

原文連結

本作品採用《CC 協議》,轉載必須註明作者和本文連結

每天5分鐘,與你一起蛻變!上海php自學中心,目前專注於php,python,golang~撒花!
S3d25uqwht.png!large
公眾號7Dn78VKKcW.jpg!large

相關文章