channel 和阻塞模式和非阻塞模式(1)

最近一直又被問到chan 的阻塞和非阻塞模式有什么區(qū)別,他們分別在什么場景下使用,寫個日記記錄下

阻塞模式

示例代碼

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int)
    ch <- 1
    time.Sleep(3 * time.Second)
    i := <-ch
    fmt.Println(i)
}

很明顯以上代碼會報錯fatal error: all goroutines are asleep - deadlock!,非阻塞channel同一時刻必須有讀端(i=:<-ch)和寫端(ch <- 1),可以理解為一個同步過程,所以有的地方把他叫做同步通道, 修改代碼如下就可以正常運(yùn)行.

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int)
    go func() {
        ch <- 1
        time.Sleep(3 * time.Second)
    }()
    i := <-ch
    fmt.Println(i)
}

應(yīng)用場景:阻塞主程序,如果能捕獲系統(tǒng)Interrupt信號,則退出主程序,執(zhí)行清理工作, 示例代碼如下

func Consumer() {
    // do something
    stop := make(chan os.Signal)

    signal.Notify(stop, os.Interrupt)
    <-stop
    endProcess()
}

func endProcess() {
    fmt.Println("我來結(jié)束程序")
    time.Sleep(3 * time.Second)
}

如果使用select 程序永遠(yuǎn)都不會報fatal error: all goroutines are asleep - deadlock!如下所示

package main

import (
    "fmt"
    "time"
)

func main() {
    messages := make(chan string)
    signals := make(chan bool)

    select {
    case msg := <-messages:
        fmt.Println("received message", msg)
    default:
        fmt.Println("no message received")
    }

    go func() { messages <- "hi" }()
    time.Sleep(1 * time.Second)
    

    select {
    case msg := <-messages:
        fmt.Println("received message", msg)
    case sig := <-signals:
        fmt.Println("received signal", sig)
    default:
        fmt.Println("no activity")
    }
}

明天爭取把非阻塞的通道補(bǔ)上。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容