go實例之輕量級線程goroutine、通道channel與select


1、goroutine線程

  goroutine是一個輕量級的執行線程。假設有一個函數調用f(s),要在goroutine中調用此函數,請使用go f(s)。 這個新的goroutine將與調用同時執行。

  示例代碼如下:

 1 package main
 2 
 3 import "fmt"
 4 
 5 func f(from string) {
 6     for i := 0; i < 3; i++ {
 7         fmt.Println(from, ":", i)
 8     }
 9 }
10 
11 func main() {
12 
13     // Suppose we have a function call `f(s)`. Here's how
14     // we'd call that in the usual way, running it
15     // synchronously.
16     f("direct")
17 
18     // To invoke this function in a goroutine, use
19     // `go f(s)`. This new goroutine will execute
20     // concurrently with the calling one.
21     go f("goroutine")
22 
23     // You can also start a goroutine for an anonymous
24     // function call.
25     go func(msg string) {
26         fmt.Println(msg)
27     }("going")
28 
29     // Our two function calls are running asynchronously in
30     // separate goroutines now, so execution falls through
31     // to here. This `Scanln` code requires we press a key
32     // before the program exits.
33     var input string
34     fmt.Scanln(&input)
35     fmt.Println("done")
36 }

  執行上面代碼,將得到以下輸出結果

1 direct : 0
2 direct : 1
3 direct : 2
4 goroutine : 0
5 goroutine : 1
6 goroutine : 2
7 going

2、通道

  通道是連接並發goroutine的管道。可以從一個goroutine向通道發送值,並在另一個goroutine中接收到這些值。

 1 package main
 2 
 3 import "fmt"
 4 
 5 func main() {
 6 
 7     // Create a new channel with `make(chan val-type)`.
 8     // Channels are typed by the values they convey.
 9     messages := make(chan string)
10 
11     // _Send_ a value into a channel using the `channel <-`
12     // syntax. Here we send `"ping"`  to the `messages`
13     // channel we made above, from a new goroutine.
14     go func() { messages <- "ping" }()//使用"<-"向通道發送消息
15 
16     // The `<-channel` syntax _receives_ a value from the
17     // channel. Here we'll receive the `"ping"` message
18     // we sent above and print it out.
19     msg := <-messages//"從通道讀取數據"
20     fmt.Println(msg)
21 }

   默認情況下,通道是未緩沖的,意味着如果有相應的接收(<- chan)准備好接收發送的值,它們將只接受發送(chan <- )。使用make的第二個參數指定緩沖大小

 1 package main
 2 
 3 import "fmt"
 4 
 5 func main() {
 6 
 7     // Here we `make` a channel of strings buffering up to
 8     // 2 values.
 9     messages := make(chan string, 2)
10 
11     // Because this channel is buffered, we can send these
12     // values into the channel without a corresponding
13     // concurrent receive.
14     messages <- "buffered"
15     messages <- "channel"
16 
17     // Later we can receive these two values as usual.
18     fmt.Println(<-messages)
19     fmt.Println(<-messages)
20 }

3、通道同步

 1 package main
 2 
 3 import "fmt"
 4 import "time"
 5 
 6 // This is the function we'll run in a goroutine. The
 7 // `done` channel will be used to notify another
 8 // goroutine that this function's work is done.
 9 func worker(done chan bool) {
10     fmt.Print("working...")
11     time.Sleep(time.Second)
12     fmt.Println("done")
13 
14     // Send a value to notify that we're done.
15     done <- true
16 }
17 
18 func main() {
19 
20     // Start a worker goroutine, giving it the channel to
21     // notify on.
22     done := make(chan bool, 1)
23     go worker(done)
24 
25     // Block until we receive a notification from the
26     // worker on the channel.
27     <-done
28 }

  當使用通道作為函數參數時,可以指定通道是否僅用於發送或接收值。這種特殊性增加了程序的類型安全性。chan<-表示發送,<-chan表示接收

4、select

  每個通道將在一段時間后開始接收值,以模擬阻塞在並發goroutines中執行的RPC操作。我們將使用select同時等待這兩個值,在每個值到達時打印它們。

 1 package main
 2 
 3 import "time"
 4 import "fmt"
 5 
 6 func main() {
 7 
 8     // For our example we'll select across two channels.
 9     c1 := make(chan string)
10     c2 := make(chan string)
11 
12     // Each channel will receive a value after some amount
13     // of time, to simulate e.g. blocking RPC operations
14     // executing in concurrent goroutines.
15     go func() {
16         time.Sleep(time.Second * 1)
17         c1 <- "one"
18     }()
19     go func() {
20         time.Sleep(time.Second * 2)
21         c2 <- "two"
22     }()
23 
24     // We'll use `select` to await both of these values
25     // simultaneously, printing each one as it arrives.
26     for i := 0; i < 2; i++ {
27         select {
28         case msg1 := <-c1:
29             fmt.Println("received", msg1)
30         case msg2 := <-c2:
31             fmt.Println("received", msg2)
32         }
33     }
34 }

5、相關文章

  Go超時(timeouts)實例

  Go非阻塞通道操作實例:使用selectdefault子句來實現非阻塞發送,接收

  Go關閉通道實例:close直接關閉通道

  Go通道范圍實例:通道關閉了,還可以接收通道中的數據

 

如果您覺得文章不錯,不妨給個打賞,寫作不易,感謝各位的支持。您的支持是我最大的動力,謝謝!!! 

 

  


很重要--轉載聲明

  1. 本站文章無特別說明,皆為原創,版權所有,轉載時請用鏈接的方式,給出原文出處。同時寫上原作者:朝十晚八 or Twowords
  2. 如要轉載,請原文轉載,如在轉載時修改本文,請事先告知,謝絕在轉載時通過修改本文達到有利於轉載者的目的。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM