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時稱爲緩衝通道less

通道是個隊列,遵循先進先出的原則函數

元素值的發送和接受都須要用接收操做符 <-3d

進入通道的並非在接受操做符右邊的那個元素,而是它的副本code

緩衝通道:協程

非緩衝通道:blog

多通道的選擇
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)

通道是用來傳遞數據的,而單項通道是不能傳遞數據的


**** 碼字不易若是對你有幫助請給個關注****

**** 愛技術愛生活 QQ羣: 894109590****

相關文章
相關標籤/搜索