首頁  >  文章  >  後端開發  >  Go的並發沒有它,就像iphone沒有網路一樣

Go的並發沒有它,就像iphone沒有網路一樣

Go语言进阶学习
Go语言进阶学习轉載
2023-07-21 14:13:52698瀏覽
    Golang的並發屬性是該語言的一個大殺器,說到並發就不能不提#Channel,你可以把它看成一個管道,透過它並發核心單元就可以發送或接收資料進行通訊。這篇文章來深入了解 channel

channel 的設計是基於 CSP 模型的。 CSP 是 Communicating Sequential Process 的簡稱,中文可以叫做通訊順序進程,是一種並發程式設計模型,由 Tony Hoare 於 1977 年提出。簡單來說,CSP 模型由並發執行的實體(線程或進程)所組成,實體之間透過發送訊息進行通信,這裡發送訊息時使用的就是通道,或者叫 channel。 CSP 模型的關鍵是專注於 channel,而不關注發送訊息的實體。 Go 語言實作了 CSP 部分理論,goroutine 對應 CSP 中並發執行的實體,channel 也就對應著 CSP 中的 channel。

建立Channel

  • Go中的Channel使用chan作為關鍵字。

  • 無緩衝chan情況下,發送和接收會一直阻塞著,直到另一方準備好。這種方式可以用來在gororutine中進行同步,- 而需要使用鎖或條件變數。

  • 有緩衝chan,可以盡量避免阻塞,提高應用的效能,典型的以時間換空間。

aChan := make(chan int)  // 创建无缓冲chan
bChan := make(chan int, N) // 创建缓冲为N的chan

賦值和取值

    從以下程式碼看不出它的巨大作用,很正常,那是因為他們兩個語句通常不在一起,例如:協程A發送數據,協程B接收數據

mchan <- value  // 发送值v到Channel ch中
value := <-mchan // 从Channel ch中接收数据,并将数据赋值给v

Select

    Selsect是取得Channel中資料最常用的方式。

select 一定程度上可以类比于 linux 中的 IO 多路复用中的 select。后者相当于提供了对多个 IO 事件的统一管理,而 Golang 中的 select 相当于提供了对多个 channel 的统一管理。当然这只是 select 在 channel 上的一种使用方法。

func main(){
    ch1 := make(chan int, 1)
    ch2 := make(chan int, 1)

    select {
        case e1 := <-ch1:
        //如果ch1通道成功读取数据,则执行该case处理语句
            fmt.Printf("1th case is selected. e1=%v",e1)
        case e2 := <-ch2:
        //如果ch2通道成功读取数据,则执行该case处理语句
            fmt.Printf("2th case is selected. e2=%v",e2)
        default:
        //如果上面case都没有成功,则进入default处理流程
            fmt.Println("default!.")
    }
}

for…range

    for …… range语句可以处理Channel。

    go func() {
        time.Sleep(1 * time.Hour)
    }()
    c := make(chan int)
    go func() {
        for i := 0; i < 10; i = i + 1 {
            c <- i
        }
        close(c)
    }()
    for i := range c {
        fmt.Println(i)
    }
    fmt.Println("Finished")

timeout

    Select很重要的一个应用就是超时处理。因为上面提供的demo,select语句就会一直阻塞着。这时候我们可能就需要一个超时操作,用来处理超时的情况。下面这个例子我们会在2秒后往channel c1中发送一个数据,但是Select设置为1秒超时,因此我们会打印出timeout 1,而不是result 1。

    c1 := make(chan string, 1)
    go func() {
        time.Sleep(time.Second * 2)
        c1 <- "result 1"
    }()
    select {
    case res := <-c1:
        fmt.Println(res)
    case <-time.After(time.Second * 1):
        fmt.Println("timeout 1")
    }

close

    Go内建的close方法就可以用来关闭channel。但如果channel 已经被关闭,继续往它发送数据会导致panic: send on closed channel:

 close(mChan)

以上是Go的並發沒有它,就像iphone沒有網路一樣的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:Go语言进阶学习。如有侵權,請聯絡admin@php.cn刪除