Go 語言基礎—— 通道(channel)
通過通訊來共享記憶體(Java是通過共享記憶體來通訊的)
定義
func service() string { time.Sleep(time.Millisecond * 50) return "Done" } func AsyncService() chan string { retCh := make(chan string, 1)//建立一個容量為1元素型別為string的通道 go func() { ret := service() fmt.Println("returned result.") retCh <- ret//將值放入通道retCh中 fmt.Println("service exited.") }() return retCh } func TestAsynService(t *testing.T) { retCh := AsyncService() otherTask() fmt.Println(<-retCh)//從通道retCh中取去出一個值 time.Sleep(time.Second * 1) }
通道建立語法: make(chan 元素型別, 容量),容量是可選值指通道最多可以快取多少元素值,這個值不能為負數
當容量為0時,稱為非緩衝通道,大於0時稱為緩衝通道
通道是個佇列,遵循先進先出的原則
元素值的傳送和接受都需要用接收操作符 <-
進入通道的並不是在接受操作符右邊的那個元素,而是它的副本
緩衝通道:
非緩衝通道:
多通道的選擇
func TestSelect(t *testing.T) { select { case ret := <-retCh1://當通道retCh1中有資料時執行 t.Log(ret) case ret := <-retCh2://當通道retCh2中有資料時執行 t.Error("time out") //default不存在 retCh1 retCh2沒資料時,協程會處在阻塞狀態 default://當通道retCh1,retCh2都沒資料時執行 t.Error("error") } }
實現通道超時控制
select {
case ret := <-retCh:
t.Log(ret)
case <-time.After(time.Second * 1): //設定超時時間
t.Error("time out")
}
channel的關閉
向關閉的通道傳送資料,會導致panic, 關閉已經關閉的通道也會導致panic;
接收操作是可以感知通道的關閉,並能安全退出
v, ok<-ch;ok為bool值, true表示正常接受, false表示通道關閉
所有的channel接收者都會在channel關閉時,立刻從阻塞等待中返回且上述 ok值為false,這個廣播機制常被利用,進行向多個訂閱者同時傳送訊號。如:退出訊號。
channel關閉原則:
(1) 誰建立的channel誰負責關閉 (2) 不要關閉有傳送者的channel (3) 作為函式引數的channel最好帶方向
程式碼:
package channel_close
import (
"fmt"
"sync"
"testing"
)
//生產者
func dataProducer(ch chan int, wg *sync.WaitGroup) {
go func() {
for i := 0; i < 10; i++ {
ch <- i
}
close(ch)
wg.Done()
}()
}
//接收者
func dataReceiver(ch chan int, wg *sync.WaitGroup) {
go func() {
for {
if data, ok := <-ch; ok {
fmt.Println(data)
} else {
break
}
}
wg.Done()
}()
}
func TestCloseChannel(t *testing.T) {
var wg sync.WaitGroup
ch := make(chan int)
wg.Add(1)
dataProducer(ch, &wg)
wg.Add(1)
dataReceiver(ch, &wg)
wg.Wait()
}
Context
·根Context:通過context.Background 0建立·
子Context: context.WithCancel(parentContext)建立
ctx, cancel := context.WithCancel(context.Background))
當前Context被取消時,基於他的子context都會被取消
·接收取消通知<-ctx.Done()
通道的高階用法
我們前面說的通道都是雙向的,即:既可以發也可以收的通道;所謂單項通就是, 只能發坐著只能收
單項通道定義:
//傳送通道(只能發不能收)
var uselessChan = make(chan<- int, 1)
//接收通道(只能收不能發)
var uselessChan1 = make(<-chan int, 1)
通道是用來傳遞資料的,而單項通道是不能傳遞資料的
**** 碼字不易如果對你有幫助請給個關注****
**** 愛技術愛生活