10.蛤蟆筆記go語言——並發

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

10.蛤蟆筆記go語言——並發

goroutine

goroutine 是由 Go 運行時環境管理的輕量級線程。

go f(x, y, z)

開啟一個新的 goroutine 執行

f(x, y, z)

f , x , y 和 z 是當前 goroutine中定義的,但是在新的 goroutine 中運行 `f`。

goroutine 在相同的地址空間中運行,因此訪問共用記憶體必須進行同步。sync 提供了這種可能,不過在Go 中並不經常用到,因為有其他的辦法。

package main

import (

         "fmt"

         "time"

)

func say(s string) {

         for i:= 0; i < 5; i++ {

                   time.Sleep(100* time.Millisecond)

                   fmt.Println(s)

         }

}

func main() {

         gosay("world")

         say("hello")

}

channel

channel 是有類型的管道,可以用 channel 操作符 <- 對其發送或者接收值。

ch <- v    // 將 v 送入 channel ch。

v := <-ch  // 從 ch 接收,並且賦值給 v。

(“箭頭”就是資料流的方向。)

和 map 與 slice 一樣,channel 使用前必須建立:

ch := make(chan int)

預設情況下,在另一端準備好之前,發送和接收都會阻塞。這使得 goroutine 可以在沒有明確的鎖或競態變數的情況下進行同步。

package main

import "fmt"

 

func sum(a []int, c chan int) {

         sum :=0

         for _,v := range a {

                   sum+= v

         }

         c <-sum //將和送入c

}

 

func main() {

         a :=[]int{7, 2, 8, -9, 4, 0}

 

         c :=make(chan int)

         gosum(a[:len(a)/2], c)

         gosum(a[len(a)/2:], c)

         x, y :=<-c, <-c //從c中擷取

 

         fmt.Println(x,y, x+y)

}

執行:

         -517 12

緩衝 channel

channel 可以是 _帶緩衝的_。為 make 提供第二個參數作為緩衝長度來初始化一個緩衝 channel:

ch := make(chan int, 100)

向緩衝 channel 發送資料的時候,只有在緩衝區滿的時候才會阻塞。當緩衝區清空的時候接受阻塞。

修改例子使得緩衝區被填滿,然後看看會發生什麼。

package main

import "fmt"

func main() {

         c :=make(chan int, 2)

         c <-1

         c <-2

         fmt.Println(<-c)

         fmt.Println(<-c)

}

執行:

         1

         2

range 和 close

寄件者可以 close 一個 channel 來表示再沒有值會被發送了。接收者可以通過指派陳述式的第二參數來測試 channel 是否被關閉:當沒有值可以接收並且 channel 已經被關閉,那麼經過v, ok := <-ch

之後 ok 會被設定為 `false`。

迴圈 `for i := range c` 會不斷從 channel 接收值,直到它被關閉。

注意: 只有寄件者才能關閉 channel,而不是接收者。向一個已經關閉的 channel 發送資料會引起 panic。 還要注意: channel 與檔案不同;通常情況下無需關閉它們。只有在需要告訴接收者沒有更多的資料的時候才有必要進行關閉,例如中斷一個 `range`。

package main

import (

         "fmt"

)

func fibonacci(n int, c chan int) {

         x, y :=0, 1

         for i:= 0; i < n; i++ {

                   c<- x

                   x,y = y, x+y

         }

         close(c)

}

 

func main() {

         c :=make(chan int, 10)

         gofibonacci(cap(c), c)

         for i:= range c {

                   fmt.Println(i)

         }

}

執行:

0

         1

         1

         2

         3

         5

         8

         13

         21

         34

select

select 語句使得一個 goroutine 在多個通訊操作上等待。

select 會阻塞,直到條件分支中的某個可以繼續執行,這時就會執行那個條件分支。當多個都準備好的時候,會隨機播放一個。

package main

import "fmt"

func fibonacci(c, quit chan int) {

         x, y :=0, 1

         for {

                   select{

                   casec <- x:

                            x,y = y, x+y

                   case<-quit:

                            fmt.Println("quit")

                            return

                   }

         }

}

func main() {

         c :=make(chan int)

         quit :=make(chan int)

         gofunc() {

                   fori := 0; i < 10; i++ {

                            fmt.Println(<-c)

                   }

                   quit<- 0

         }()

         fibonacci(c,quit)

}

執行:

         0

         1

         1

         2

         3

         5

         8

         13

         21

         34

         quit

預設選擇

當 select 中的其他條件分支都沒有準備好的時候,`default` 分支會被執行。

為了非阻塞的發送或者接收,可使用 default 分支:

select {

case i := <-c:

   // 使用 i

default:

   // 從 c 讀取會阻塞

}

package main

import (

         "fmt"

         "time"

)

func main() {

         tick :=time.Tick(100 * time.Millisecond)

         boom :=time.After(500 * time.Millisecond)

         for {

                   select{

                   case<-tick:

                            fmt.Println("tick.")

                   case<-boom:

                            fmt.Println("BOOM!")

                            return

                   default:

                            fmt.Println("    .")

                            time.Sleep(50* time.Millisecond)

                   }

         }

}

執行:

.

             .

         tick.

             .

             .

         tick.

             .

             .

         tick.

             .

             .

         tick.

             .

             .

         BOOM!

入門結束

Go文檔 是一個極好的 開始。 它包含了參考、指南、視頻等等更多資料。

瞭解如何組織 Go 代碼並在其上工作,參閱 這個視頻,或者閱讀 如何編寫 Go 代碼。

在標準庫上需要協助的話,參考 包手冊。語言本身的協助,閱讀 語言規範是件令人愉快的事情。

進一步探索 Go 的並行存取模型,參閱 Go並行存取模型 (投影片) 以及 深入 Go 並行存取模型 (投影片) 並且閱讀 使用通訊共用記憶體 的代碼之旅。

想要開始編寫 Web 應用程式,參閱 一個簡單的編程環境 (投影片) 並且閱讀 編寫 Web應用 的指南.

GO中的一等公民函數 展示了有趣的函數類型。

Go Blog 有著眾多的關於 Go 的文章資訊。

mikespook的部落格有大量中文的關於 Go 的文章和翻譯。

開源電子書 GoWeb編程 和 Go入門指南 能夠協助你更加深入的瞭解和學習 Go 語言。

訪問 golang.org 瞭解更多內容。

關於本項目(中文)的任何意見、建議,請在這裡提交 Issues。

 

 

 

相關文章

聯繫我們

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