1. 程式人生 > >go channel例子

go channel例子

情況 開啟 style mono 發送數據 cnblogs 接收 println lec

channel初步認識:
package main
 
import "fmt"
import "time"
 
func main() {
c := make(chan int) //初始化一個管道
defer close(c) //在main函數執行完畢之後執行。
go func() { //會開啟一個協程,並往管道c寫入數據
time.Sleep(2 * time.Second)
fmt.Println("all ready")
c <- 3 + 4
}()
i := <-c // 將管道c的內容輸出賦值到i,在c還沒有內容的時候,會一直阻塞在這裏。
fmt.Println(i) //
打印i的值 } [[email protected] hello]# go run channel.go all ready 7

如註釋所示,在管道還沒有內容輸入之前i := <-c這個語句一直被阻塞著。 往一個已經被close的channel中繼續發送數據會導致run-time panic。 如下:
package main
 
import "fmt"
import "time"
 
func main() {
c := make(chan int) //初始化一個管道
go func() { //會開啟一個協程,並往管道c寫入數據
time.Sleep(2 * time.Second) fmt.Println("all ready") c <- 3 + 4 close(c) }() i := <-c // 將管道c的內容輸出賦值到i,在c還沒有內容的時候,會一直阻塞在這裏。 fmt.Println(i) //打印i的值 c <- 8 //由於c已經在協程裏面被關閉,這句將引起run-time panic } 輸出結果如下: [[email protected] hello]# go run channel.go all ready 7 panic: send on closed channel goroutine
1 [running]: main.main() /mnt/hgfs/share/eclipse/testgo/src/hello/channel.go:16 +0x125 exit status 2

可以使用一個額外的返回參數來檢查channel是否關閉。 x, ok := <-ch 如果OK 是false,表明接收的x是產生的零值,這個channel被關閉了或者為空。 另一種是可以用for range處理這種管道是否有數據的情況,在管道被關閉時for range會退出。
func main() {
go func() {
time.Sleep(1 * time.Hour)
}()
c := make(chan int)
go func() {
for i := 0; i < 10; i = i + 1 {
c <- i
}
close(c) //如果將此句註釋掉,那麽下面的for range在打印完管道的內容後會一直阻塞。
}()
for i := range c {
fmt.Println(i)
}
fmt.Println("Finished")
}

select 類似於switch,裏面的case可以是recieve或send或default語句。 如果同時有多個case滿足條件,那麽Go會偽隨機的選擇一個case處理,如果沒有case需要處理,則會選擇default去處理。如果沒有default case,則select語句會阻塞,直到某個case需要處理。
package main
 
import (
"fmt"
)
 
func fab(c, quit chan int) {
x, y := 0, 1
 
for {
select {
case c <- x:
x, y = y, x+y
case <-quit:
return
}
}
 
}
 
func main() {
c := make(chan int)
quit := make(chan int)
 
go func() {
for i := 0; i < 10; i++ {
fmt.Println(<-c)
}
quit <- 0
}()
 
fab(c, quit)
 
}
 
[[email protected] hello]# go run channel.go
0
1
1
2
3
5
8
13
21
34

超時處理:
package main
 
import (
"fmt"
"time"
)
 
func main() {
 
c := make(chan string)
 
go func() {
time.Sleep(30 * time.Second)
c <- "Hello World"
}()
 
select {
case res := <-c:
fmt.Println(res)
case <-time.After(2 * time.Second):
fmt.Println("timeout")
}
 
}
[[email protected] hello]# go run channel.go
timeout

參考來源:http://colobu.com/2016/04/14/Golang-Channels/

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

go channel例子