概念及作用
channel是一個資料型別,用於實現同步,用於兩個協程之間交換資料。goroutine奉行通過通訊來共享記憶體,而不是共享記憶體來通訊。
引用型別channel是CSP模式的具體實現,用於多個goroutine通訊。其內部實現了同步,確保併發安全。
建立及使用
每個channel在建立的時候必須指定一個型別,指定的型別是任意的。
ch := make(chan int) //使用內建的make函式,可以建立一個channel型別
// 傳送資料到channel
ch <- 1
// 從channel接受資料
x := <- ch
案例舉例(一)
①建立channel前
package main
import (
"fmt"
"time"
)
//定義一個印表機,引數為字串,按每個字元列印
//印表機屬於公共資源
func Printer(str string) {
for _, data := range str {
fmt.Printf("%c", data)
time.Sleep(time.Second)
}
fmt.Printf("\n")
}
func person1() {
Printer("hello")
}
func person2() {
Printer("world")
}
func main() {
//新建2個協程,代表2個人,2個人同時使用印表機
go person1()
go person2()
//特地不讓主協程結束,死迴圈
for {
}
}
//結果
hwoerllldo //交叉執行
②建立channel後(注意channel變數和呼叫的先後順序)
package main
import (
"fmt"
"time"
)
//全域性變數,建立一個channel
var ch = make(chan int)
//定義一個印表機,引數為字串,按每個字元列印
//印表機屬於公共資源
func Printer(str string) {
for _, data := range str {
fmt.Printf("%c", data)
time.Sleep(time.Second)
}
fmt.Printf("\n")
}
//person1執行完後,才能到person2執行
func person1() {
Printer("hello")
ch <- 666 //給管道寫資料,傳送
}
func person2() {
<-ch //從管道取資料,接收,如果通道沒有資料他就會阻塞
Printer("world")
}
func main() {
//新建2個協程,代表2個人,2個人同時使用印表機
go person1()
go person2()
//特地不讓主協程結束,死迴圈
for {
}
}
hello
world
案例舉例(二)
package main
import (
"fmt"
)
func main() {
ch := make(chan string)
go func() {
fmt.Println("aaaaaaaaaa")
str := <-ch // 在執行到這一步的時候main goroutine才會停止阻塞
fmt.Println("取出channel的資料" + str)
}()
fmt.Println("bbbbbbbbbb")
ch <- "hello" // 如果沒有其他goroutine來取走這個資料,main goroutine掛起,直到其它gorouteine把資料拿走(這裡會暫時阻塞)
fmt.Println("cccccccccc")
}
bbbbbbbbbb
aaaaaaaaaa
取出channel的資料hello
cccccccccc