日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

GoLang?channel使用介紹_Golang

作者:~龐貝 ? 更新時間: 2022-11-22 編程語言

停止信號

channel 用于停止信號的場景還是挺多的,經常是關閉某個 channel 或者向 channel 發送一個元素,使得接收 channel 的那一方獲知道此信息,進而做一些其他的操作。

任務定時

與 timer 結合,一般有兩種玩法:實現超時控制,實現定期執行某個任務。

有時候,需要執行某項操作,但又不想它耗費太長時間,上一個定時器就可以搞定:

select {
	case <-time.After(100 * time.Millisecond):
	case <-s.stopc:
		return false
}

等待 100 ms 后,如果 s.stopc 還沒有讀出數據或者被關閉,就直接結束。這是來自 etcd 源碼里的一個例子,這樣的寫法隨處可見。

定時執行某個任務,也比較簡單:

func worker() {
	ticker := time.Tick(1 * time.Second)
	for {
		select {
		case <- ticker:
			// 執行定時任務
			fmt.Println("執行 1s 定時任務")
		}
	}
}

每隔 1 秒種,執行一次定時任務。

解耦生產方和消費方

服務啟動時,啟動 n 個 worker,作為工作協程池,這些協程工作在一個 for {} 無限循環里,從某個 channel 消費工作任務并執行:

func main() {
	taskCh := make(chan int, 100)
	go worker(taskCh)
    // 塞任務
	for i := 0; i < 10; i++ {
		taskCh <- i
	}
    // 等待 1 小時 
	select {
	case <-time.After(time.Hour):
	}
}
func worker(taskCh <-chan int) {
	const N = 5
	// 啟動 5 個工作協程
	for i := 0; i < N; i++ {
		go func(id int) {
			for {
				task := <- taskCh
				fmt.Printf("finish task: %d by worker %d\n", task, id)
				time.Sleep(time.Second)
			}
		}(i)
	}
}

5 個工作協程在不斷地從工作隊列里取任務,生產方只管往 channel 發送任務即可,解耦生產方和消費方。

finish task: 1 by worker 4
finish task: 2 by worker 2
finish task: 4 by worker 3
finish task: 3 by worker 1
finish task: 0 by worker 0
finish task: 6 by worker 0
finish task: 8 by worker 3
finish task: 9 by worker 1
finish task: 7 by worker 4
finish task: 5 by worker 2

控制并發數

有時需要定時執行幾百個任務,例如每天定時按城市來執行一些離線計算的任務。但是并發數又不能太高,因為任務執行過程依賴第三方的一些資源,對請求的速率有限制。這時就可以通過 channel 來控制并發數。

下面的例子來自《Go 語言高級編程》:

var limit = make(chan int, 3)
func main() {
    // …………
    for _, w := range work {
        go func() {
            limit <- 1
            w()
            <-limit
        }()
    }
    // …………
}

構建一個緩沖型的 channel,容量為 3。接著遍歷任務列表,每個任務啟動一個 goroutine 去完成。真正執行任務,訪問第三方的動作在 w() 中完成,在執行 w() 之前,先要從 limit 中拿“許可證”,拿到許可證之后,才能執行 w(),并且在執行完任務,要將“許可證”歸還。這樣就可以控制同時運行的 goroutine 數。

這里,limit <- 1 放在 func 內部而不是外部,原因是:

如果在外層,就是控制系統 goroutine 的數量,可能會阻塞 for 循環,影響業務邏輯。

limit 其實和邏輯無關,只是性能調優,放在內層和外層的語義不太一樣。

還有一點要注意的是,如果 w() 發生 panic,那“許可證”可能就還不回去了,因此需要使用 defer 來保證。

原文鏈接:https://blog.csdn.net/qq_53267860/article/details/126918536

欄目分類
最近更新