go語言學習-goroutine

來源:互聯網
上載者:User

標籤:can   package   span   bool   ...   導致   second   string   效果   

o 語言有一個很重要的特性就是 goroutine, 我們可以使用 goroutine 結合 channel 來開發並發程式。

並發程式指的是可以同時運行多個任務的程式,這裡的同時運行並不一定指的是同一時刻執行,在單核CPU的機器下,在同一時刻只可能有一個任務在執行,但是由於CPU的速度很快,在不斷的切換著多個任務,讓它們交替的執行,因此宏觀上看起來就像是同時在運行; 而在多核的機器上,並發程式中的多個任務是可以實現在同一時刻執行多個的,此時並發的多個任務是在並存執行的。

goroutine

goroutine 是 go 語言中的並發執行單元,我們可以將多個任務分別放在多個 goroutine 中,來實現並發程式。下面先看一個例子:

package mainimport "fmt"func hello() {    fmt.Println("Hello World!!!")}func main() {    go hello()    fmt.Println("Bye!!!")    var input string    fmt.Scanln(&input)}

上述程式的執行結果如下:

Bye!!!Hello World!!!

上面這個例子展示了使用 goroutine 的幾個要點:

  1. 程式啟動時,我們的主函數 main 也是在一個單獨的 goroutine 中啟動並執行。
  2. go hello() 就是用於建立一個 goroutine, 即 go 關鍵字加上 要在 goroutine 中執行的函數(也可以是匿名函數,不過必須是調用的形式)
  3. 最後兩句是用於將 main 函數阻塞在這裡,直到我們按下斷行符號鍵,之所以這麼做是因為,我們不知道新建立的 goroutine 和 main goroutine 的執行順序,有可能主程式先執行完成,此時主程式結束,我們就看不到新 goroutine 的執行效果了。(通常不會使用這種方法)

以上就是 goroutine 的基本用法

channels

前面我們學習了怎樣建立並行的執行單元,但是每個執行單元之間是完全獨立的,如果我們想在運行期間交換資料,即進行通訊,此時就得依靠另一個概念 - channels, 即通道,這個名字十分貼切,就像在不同的並發執行單元之間串連了一根管道,然後通過這跟管道來發送和接收資料。

goroutine 和 channel 經常結合在一起使用,下面學習一些 channel 的用法:

  1. 建立 channel

    ch1 := make(chan int)

    channel 也需要使用 make 函數來建立,也就是說 channel 也是一種參考型別(make函數會返回低層資料結構的引用給channel)

  2. 向 channel 中讀寫資料

    前面說了 channel 是用於 goroutine 之間通訊的, 自然能夠從 channel 中寫入和讀取資料,使用的都是 <- 操作符

    ch := make(chan int)ch<- 1              // 向 channel 中寫入資料var a int = <-ch    // 從 channel 中讀取資料
  3. 關閉 channel
    在我們使用完一個 channel 之後,可以調用 close() 方法來關閉一個 channel, 關閉之後的通道,不能夠再進行資料的寫操作, 但是仍然可以讀取之前寫入成功的資料(如果沒有資料了,將返回零值)。

channel 的基本操作就是上面這麼多,不過實際上,channel 是有兩種的: 無緩衝的 和 有緩衝的。上面我們建立的是無緩衝的,有緩衝的建立方式是 ch := make(chan int, 2), 二者的區別是:

  1. 無緩衝的 channel 的發送操作將導致寄件者的 goroutine 阻塞,直到在另一個 goroutine 上對其進行接收操作。如果先發生的是接收操作,那麼接收者將被阻塞,直到在另一個 goroutine 上對其進行發送操作。
  2. 帶緩衝的 channel 可以緩衝多個資料,因此不會立即阻塞,只有當緩衝滿了之後,寄件者才可能會被阻塞,並且只有到緩衝為空白時,接收者才可能被阻塞

例1: 通道用於傳遞訊息

package mainimport "fmt"func main() {    message := make(chan string)        // 建立一個用於傳遞字串的通道    go func() {        message <- "This is a message."   // 向 channel 寫入資料    }()    msg := <- message       // 從 channel 讀取資料    fmt.Println(msg)}

例2: 利用通道進行同步

package mainimport "fmt"func hello() {    fmt.Println("Hello World!!!")    done <- true          }func main() {    done := make(chan bool)    go hello()    fmt.Println("Bye!!!")    <-done           // 這裡會阻塞住,直到在另一個 goroutine 中對 done 進行寫入操作之後}
單向 channel

當使用 channel 作為參數,我們可以指定 channel 為單向的,即讓通道在函數中只能發送,或者只能接收資料,以此來提高程式的安全性.

文法:

  • <-chan type 表示一個只能接收資料的通道
  • chan<- type 表示一個只能發送資料的通道

例子:

package mainimport "fmt"// 這裡的 message 在函數 send 中就是一個只能發送資料的通道func send(msg string, message chan<- string) {    message<- msg}// 這裡的 message 在函數 receive 中就是一個只能發送資料的通道func receive(message <-chan string) string {    msg := <- message    return msg}func main() {    message := make(chan string)    go send("hello", message)    fmt.Println(receive(message))}

輸出結果是 hello, 此時在函數 send 中,message 通道就只能用於發送資料,而在函數 receive 中通道只能接收資料,通過參數的限制使其在函數內部成為了單向的通道。

select

go語言提供了一個 select 關鍵字,可以使用它來等待多個通道的操作,以實現多工。文法:

select {    case <-ch1:        ...    case ch2 <- value:        ...    default:        ...}

其中的每個 case 表示一個 channel 的操作,當case語句後面指定通道的操作可以執行時,select 才會執行 case 之後的語句。此時其他的語句都不會被執行。

例子: 逾時處理

package mainimport "time"import "fmt"func main() {    ch1 := make(chan string, 1)    go func() {        time.Sleep(time.Second * 2)        ch1 <- "result 1"    }()    select {        case res := <- ch1:            fmt.Println(res)        case <-time.After(time.Second * 1):            fmt.Println("timeout 1")    }    ch2 := make(chan string, 1)    go func() {        time.Sleep(time.Second * 2)        ch2 <- "result 2"    }()    select {    case res := <-ch2:        fmt.Println(res)    case <-time.After(time.Second * 3):        fmt.Println("timeout 2")    }}

上面的例子中我們定義了兩個通道和兩個select結構,是為了進行對比,第一個channel會在等待兩秒之後被寫入資料,而在 select 中,第二個case語句只會等待一秒,然後就會執行,因此就會執行逾時操作。而在第二個 select 中,第二個 case 語句會等待三秒。所以上述程式的結果如下:

timeout 1result 2

go語言學習-goroutine

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.