偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Go 語言內(nèi)置 I/O 多路復(fù)用機制

開發(fā) 前端
本文我們了解到 select? 中的 case? 語句可以讀取 channel?,多個 case 語句僅能其中 1 個被執(zhí)行。

01 介紹

Go 協(xié)程之間通過 channel 通信,但是 channel 讀寫取決于自身特性,即是否有可寫入緩沖區(qū)、緩沖區(qū)中是否有數(shù)據(jù)、是否已關(guān)閉...

為了檢測 channel 的特性,Go 提供了一個關(guān)鍵字 select,可用于實現(xiàn) I/O 多路復(fù)用機制。

本文我們介紹 Go 關(guān)鍵字 select 的使用方式。

02 使用方式

Go 關(guān)鍵字 select 中包含 case 語句和 default 語句,其中 default 語句可以認為是一種特殊的 case 語句。

因為 default 語句不負責(zé)處理 channel 的讀寫,它可以在 select 中的任意位置,且僅能包含一個 default 語句。在所有 case 語句都不滿足執(zhí)行條件時,default 語句將被執(zhí)行(建議盡量不要省略 default 語句)。

我們通過代碼片段,分別介紹 select 在檢測到 channel 不同特性時,得到的運行結(jié)果。

空 select

接下來,我們閱讀一段代碼。

func main() {
 fmt.Println("Golang 語言開發(fā)棧")
 go func() {
  fmt.Println("Golang 公眾號")
 }()
}

閱讀上面這段代碼,讀者朋友們認為 Go 協(xié)程中的打印語句可以正常輸出嗎?

讀者朋友們?nèi)绻\行代碼,會發(fā)現(xiàn) Go 協(xié)程中的打印語句還沒有執(zhí)行,程序就已經(jīng)退出了,這是因為 main 函數(shù)中的打印語句已經(jīng)執(zhí)行完成,所以會退出程序。

如果我們希望 Go 協(xié)程中的打印語句也執(zhí)行,可以在 main 函數(shù)中使用 select{} 將 main 阻塞,Go 協(xié)程中的打印語句就有機會執(zhí)行了。但是,這會導(dǎo)致死鎖(可以根據(jù)實際應(yīng)用場景選擇是否使用)。

無緩沖 channel

接下來,我們再讀一段可以導(dǎo)致死鎖的代碼:

func main() {
 c := make(chan string)
 DoChannel(c)
}

func DoChannel(c chan string) {
 var receive string
 send := "golang"
 select {
 case receive = <-c:
  fmt.Println(receive)
 case c <- send:
  fmt.Println(send)
 }
}

閱讀上面這段代碼,我們定義一個函數(shù) DoChannel(),該函數(shù)接收的參數(shù)是一個 string 類型的 channel,函數(shù)體中使用 select 中的兩個 case 語句,分別對參數(shù)進行接收和發(fā)送操作。

運行代碼,select 阻塞。

因為,我們傳參的 c 是無緩沖 channel,所以它即不能讀也不能寫,兩個 case 語句都不執(zhí)行,select 陷入阻塞,導(dǎo)致死鎖(此處為了行文,故意沒有 default 語句)。

無數(shù)據(jù),有緩沖channel

我們將上面這段代碼,稍微修改一下,將入?yún)⒌?nbsp;c 改為 1 個緩沖區(qū)大小的 channel(未寫入數(shù)據(jù))。代碼如下:

func main() {
 c := make(chan string, 1)
 DoChannel(c)
}

運行代碼,寫執(zhí)行,讀未執(zhí)行。

即 select 中的對入?yún)?nbsp;channel 進行發(fā)送操作的 case 語句被執(zhí)行,因為入?yún)?nbsp;c 是一個有 1 個緩沖區(qū)大小的 channel,并且該 channel 中還沒有數(shù)據(jù),所以讀取操作的 case 語句沒有讀取到數(shù)據(jù),不滿足執(zhí)行條件。

有緩沖區(qū),已寫滿數(shù)據(jù) channel

我們再修改一下入?yún)?nbsp;c,將入?yún)⒌?nbsp;c 改為 1 個緩沖區(qū)大小的 channel,并且寫入字符串 Go。代碼如下:

func main() {
 c := make(chan string, 1)
 c <- "Go"
 DoChannel(c)
}

運行代碼,讀執(zhí)行,寫未執(zhí)行。

即 select 中的對入?yún)?nbsp;channel 進行接收操作的 case 語句被執(zhí)行,因為入?yún)?nbsp;c 是一個有 1 個緩沖區(qū)大小,并且已寫滿數(shù)據(jù),所以讀取操作的 case 語句可以讀取到數(shù)據(jù),滿足執(zhí)行條件。

而寫入操作的 case 無法寫入數(shù)據(jù),不滿足執(zhí)行條件。

有緩沖區(qū),有數(shù)據(jù),可寫數(shù)據(jù) channel

最后一種場景是既能讀取也能寫入的 channel,我們修改一下入?yún)?nbsp;c,將入?yún)?nbsp;c 改為 2 個緩沖區(qū)大小的 channel,其中 1 個緩沖區(qū)寫入字符串 Go,另外 1 個緩沖區(qū)還可以寫入數(shù)據(jù)。代碼如下:

func main() {
 c := make(chan string, 2)
 c <- "Go"
 DoChannel(c)
}

通過多次運行代碼,會發(fā)現(xiàn)讀取和寫入的 case 語句都有機會執(zhí)行,因為兩個 case 語句都滿足執(zhí)行條件,但是只能有 1 個 case 語句執(zhí)行,select 會隨機執(zhí)行其中 1 個 case 語句。

至此,我們已經(jīng)介紹了 5 種 channel 在 select 中的運行結(jié)果。

case 語句中聲明變量

上面的代碼中,我們發(fā)現(xiàn)在兩個 case 語句中,讀操作我們將讀取到的數(shù)據(jù)賦值給變量 receive,實際上,我們也可以省略變量賦值操作。

如果我們需要將讀取到的數(shù)據(jù),賦值給變量的話,一般建議將讀取 channel 返回的兩個值全部接收,其中一個是讀取到的數(shù)據(jù),另外一個是布爾值,代表 channel 中沒有數(shù)據(jù),并且已被關(guān)閉。代碼如下:

func main() {
 c := make(chan string)
 close(c)
 DoChannelV2(c)
}

func DoChannelV2(c chan string) {
 var (
  receive string
  ok      bool
 )
 select {
 case receive, ok = <-c:
  if !ok {
   fmt.Println("no data")
  } else {
   fmt.Println(receive)
  }
 }
}

閱讀上面這段代碼,我們使用 close 將 c 關(guān)閉。select 中的讀操作 case 語句,可以通過 ok 的值,得到 channel 中沒有數(shù)據(jù),且已被關(guān)閉,不必打印空數(shù)據(jù)。

03 總結(jié)

本文我們了解到 select 中的 case 語句可以讀取 channel,多個 case 語句僅能其中 1 個被執(zhí)行。

每個 case 語句僅能對 1 個 channel 進行讀寫操作,如果讀操作未讀取到數(shù)據(jù)將陷入阻塞,如果寫操作無法寫入數(shù)據(jù)將陷入阻塞,如果所有 case 語句中的 channel 都陷入阻塞時,select 也會陷入阻塞。

為了避免 select 陷入阻塞,我們可以使用 default 語句,需要注意的是,default 語句可以在 select 的任意位置,但是僅能包含 1 個,而 case 語句可以包含多個。

責(zé)任編輯:武曉燕 來源: Golang語言開發(fā)棧
相關(guān)推薦

2023-12-06 07:16:31

Go語言語句

2021-03-17 16:53:51

IO多路

2021-02-10 08:09:48

Netty網(wǎng)絡(luò)多路復(fù)用

2021-03-24 08:03:38

NettyJava NIO網(wǎng)絡(luò)技術(shù)

2020-10-13 07:51:03

五種IO模型

2020-10-14 09:11:44

IO 多路復(fù)用實現(xiàn)機

2025-05-08 08:01:05

2024-12-30 00:00:05

2023-11-08 09:22:14

I/ORedis阻塞

2021-06-09 19:25:13

IODubbo

2022-08-26 00:21:44

IO模型線程

2019-12-23 14:53:26

IO復(fù)用

2023-01-09 10:04:47

IO多路復(fù)用模型

2023-08-07 08:52:03

Java多路復(fù)用機制

2011-12-08 10:51:25

JavaNIO

2021-05-31 06:50:47

SelectPoll系統(tǒng)

2009-06-29 18:09:12

多路復(fù)用Oracle

2022-07-11 08:02:15

KafkaSelector

2024-08-08 14:57:32

2023-11-07 08:19:35

IO多路復(fù)用磁盤、
點贊
收藏

51CTO技術(shù)棧公眾號