欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

golang中select語(yǔ)句的簡(jiǎn)單實(shí)例

 更新時(shí)間:2022年06月29日 11:56:39   作者:燕雙鷹...  
Go的select語(yǔ)句是一種僅能用于channl發(fā)送和接收消息的專用語(yǔ)句,此語(yǔ)句運(yùn)行期間是阻塞的,下面這篇文章主要給大家介紹了關(guān)于golang中select語(yǔ)句的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

在golang語(yǔ)言中,select語(yǔ)句 就是用來(lái)監(jiān)聽(tīng)和channel有關(guān)的IO操作,當(dāng)IO操作發(fā)生時(shí),觸發(fā)相應(yīng)的case動(dòng)作。有了 select語(yǔ)句,可以實(shí)現(xiàn) main主線程 與 goroutine線程 之間的互動(dòng)。

select {
    case <-ch1 :     // 檢測(cè)有沒(méi)有數(shù)據(jù)可讀
        // 一旦成功讀取到數(shù)據(jù),則進(jìn)行該case處理語(yǔ)句
    case ch2 <- 1 :  // 檢測(cè)有沒(méi)有數(shù)據(jù)可寫(xiě)
        // 一旦成功向ch2寫(xiě)入數(shù)據(jù),則進(jìn)行該case處理語(yǔ)句
    default:
        // 如果以上都沒(méi)有符合條件,那么進(jìn)入default處理流程
}

注意事項(xiàng):

  • select語(yǔ)句 只能用于channel信道的IO操作,每個(gè)case都必須是一個(gè)信道。
  • 如果不設(shè)置 default條件,當(dāng)沒(méi)有IO操作發(fā)生時(shí),select語(yǔ)句就會(huì)一直阻塞;
  • 如果有一個(gè)或多個(gè)IO操作發(fā)生時(shí),Go運(yùn)行時(shí)會(huì)隨機(jī)選擇一個(gè)case執(zhí)行,但此時(shí)將無(wú)法保證執(zhí)行順序;
  • 對(duì)于case語(yǔ)句,如果存在信道值為nil的讀寫(xiě)操作,則該分支將被忽略,可以理解為相當(dāng)于從select語(yǔ)句中刪除了這個(gè)case;
  • 對(duì)于空的 select語(yǔ)句,會(huì)引起死鎖;
  • 對(duì)于在 for中的select語(yǔ)句,不能添加 default,否則會(huì)引起cpu占用過(guò)高的問(wèn)題;

1.先舉個(gè)簡(jiǎn)單例子

先創(chuàng)建兩個(gè)信道,并在 select 前往 c2 發(fā)送數(shù)據(jù)

package main
 
import (
	"fmt"
)
 
//go的通道選擇器 讓你可以同時(shí)等待多個(gè)通道操作。go協(xié)程和通道以及選擇器的結(jié)合是go的一個(gè)強(qiáng)大特性。
 
func main() {
	// 在我們的例子中,我們將從兩個(gè)通道中選擇。
	c1 := make(chan string, 1)
	c2 := make(chan string, 1)
 
	c2 <- "nihao"
 
	//go func() {
	//	time.Sleep(time.Second * 1)
	//	c1 <- "one"
	//}()
	//
	//go func() {
	//	time.Sleep(time.Second * 2)
	//	c2 <- "two"
	//}()
 
	//我們使用 `select` 關(guān)鍵字來(lái)同時(shí)等待這兩個(gè)值,并打印各自接收到的值。
	//for i := 0; i < 2; i++ {
	select {
	case msg1 := <-c1:
		fmt.Println("received", msg1)
	case msg2 := <-c2:
		fmt.Println("received", msg2)
	default:
		fmt.Println("No data received")
	}
	//}
 
}

在運(yùn)行 select 時(shí),會(huì)遍歷所有(如果有機(jī)會(huì)的話)的 case 表達(dá)式,只要有一個(gè)信道有接收到數(shù)據(jù),那么 select 就結(jié)束,所以輸出如下

2. 避免造成死鎖

select 在執(zhí)行過(guò)程中,必須命中其中的某一分支。

如果在遍歷完所有的 case 后,若沒(méi)有命中(命中:也許這樣描述不太準(zhǔn)確,我本意是想說(shuō)可以執(zhí)行信道的操作語(yǔ)句)任何一個(gè) case 表達(dá)式,就會(huì)進(jìn)入 default 里的代碼分支。

package main
 
import (
	"fmt"
)
 
//go的通道選擇器 讓你可以同時(shí)等待多個(gè)通道操作。go協(xié)程和通道以及選擇器的結(jié)合是go的一個(gè)強(qiáng)大特性。
 
func main() {
	// 在我們的例子中,我們將從兩個(gè)通道中選擇。
	c1 := make(chan string, 1)
	c2 := make(chan string, 1)
 
	//c2 <- "nihao"
 
	//go func() {
	//	time.Sleep(time.Second * 1)
	//	c1 <- "one"
	//}()
	//
	//go func() {
	//	time.Sleep(time.Second * 2)
	//	c2 <- "two"
	//}()
 
	//我們使用 `select` 關(guān)鍵字來(lái)同時(shí)等待這兩個(gè)值,并打印各自接收到的值。
	//for i := 0; i < 2; i++ {
	select {
	case msg1 := <-c1:
		fmt.Println("received", msg1)
	case msg2 := <-c2:
		fmt.Println("received", msg2)
		//default:
		//	fmt.Println("No data received")
		//}
	}
}

 但如果你沒(méi)有寫(xiě) default 分支,select 就會(huì)阻塞,直到有某個(gè) case 可以命中,而如果一直沒(méi)有命中,select 就會(huì)拋出 deadlock 的錯(cuò)誤,就像下面這樣子。

1.解決這個(gè)問(wèn)題的方法有兩種

一個(gè)是,養(yǎng)成好習(xí)慣,在 select 的時(shí)候,也寫(xiě)好 default 分支代碼,盡管你 default 下沒(méi)有寫(xiě)任何代碼。

 另一個(gè)是,讓其中某一個(gè)信道可以接收到數(shù)據(jù)

3. select 隨機(jī)性

之前學(xué)過(guò) switch 的時(shí)候,知道了 switch 里的 case 是順序執(zhí)行的,但在 select 里卻不是。

通過(guò)下面這個(gè)例子的執(zhí)行結(jié)果就可以看出

4. select 的超時(shí)

當(dāng) case 里的信道始終沒(méi)有接收到數(shù)據(jù)時(shí),而且也沒(méi)有 default 語(yǔ)句時(shí),select 整體就會(huì)阻塞,但是有時(shí)我們并不希望 select 一直阻塞下去,這時(shí)候就可以手動(dòng)設(shè)置一個(gè)超時(shí)時(shí)間。

5. 讀取/寫(xiě)入都可以

上面例子里的 case,好像都只從信道中讀取數(shù)據(jù),但實(shí)際上,select 里的 case 表達(dá)式只要求你是對(duì)信道的操作即可,不管你是往信道寫(xiě)入數(shù)據(jù),還是從信道讀出數(shù)據(jù)。

6. 總結(jié)一下

select 與 switch 原理很相似,但它的使用場(chǎng)景更特殊,學(xué)習(xí)了本篇文章,你需要知道如下幾點(diǎn)區(qū)別:

  1. select 只能用于 channel 的操作(寫(xiě)入/讀出),而 switch 則更通用一些;
  2. select 的 case 是隨機(jī)的,而 switch 里的 case 是順序執(zhí)行;
  3. select 要注意避免出現(xiàn)死鎖,同時(shí)也可以自行實(shí)現(xiàn)超時(shí)機(jī)制;
  4. select 里沒(méi)有類似 switch 里的 fallthrough 的用法;
  5. select 不能像 switch 一樣接函數(shù)或其他表達(dá)式。

到此這篇關(guān)于golang中select語(yǔ)句的文章就介紹到這了,更多相關(guān)go中select語(yǔ)句內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語(yǔ)言開(kāi)發(fā)區(qū)塊鏈只需180行代碼(推薦)

    Go語(yǔ)言開(kāi)發(fā)區(qū)塊鏈只需180行代碼(推薦)

    這篇文章主要介紹了Go語(yǔ)言開(kāi)發(fā)區(qū)塊鏈只需180行代碼,文章中將不會(huì)涉及工作量證明算法(PoW)以及權(quán)益證明算法(PoS)這類的共識(shí)算法。需要的朋友可以參考下
    2018-05-05
  • 如何利用Golang寫(xiě)出高并發(fā)代碼詳解

    如何利用Golang寫(xiě)出高并發(fā)代碼詳解

    今天領(lǐng)導(dǎo)問(wèn)起為什么用Golang,同事回答語(yǔ)法簡(jiǎn)單,語(yǔ)言新,支持高并發(fā)。那高并發(fā)到底如何實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于如何利用Golang寫(xiě)出高并發(fā)代碼的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-09-09
  • 用Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)實(shí)現(xiàn)Web服務(wù)之項(xiàng)目介紹

    用Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)實(shí)現(xiàn)Web服務(wù)之項(xiàng)目介紹

    從本節(jié)開(kāi)始將從后端到前端一步一步實(shí)現(xiàn)一個(gè)Go語(yǔ)言Web服務(wù),后端除了MySQL驅(qū)動(dòng),全部使用Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)來(lái)實(shí)現(xiàn)一個(gè)小型項(xiàng)目,本篇將簡(jiǎn)單的介紹一下項(xiàng)目開(kāi)發(fā)要準(zhǔn)備的流程,感興趣的同學(xué)可以閱讀一下
    2023-05-05
  • Golang實(shí)踐筆錄之讀取yaml配置文件

    Golang實(shí)踐筆錄之讀取yaml配置文件

    YAML是YAML?Ain't?a?Markup?Language的縮寫(xiě),YAML不是一種標(biāo)記語(yǔ)言,相比JSON格式的方便,這篇文章主要給大家介紹了關(guān)于Golang實(shí)踐筆錄之讀取yaml配置文件的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • Go?Excelize?API源碼閱讀Close及NewSheet方法示例解析

    Go?Excelize?API源碼閱讀Close及NewSheet方法示例解析

    這篇文章主要為大家介紹了Go?Excelize?API源碼閱讀Close及NewSheet方法示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Go?語(yǔ)言進(jìn)階單元測(cè)試示例詳解

    Go?語(yǔ)言進(jìn)階單元測(cè)試示例詳解

    這篇文章主要為大家介紹了Go?語(yǔ)言進(jìn)階單元測(cè)試示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • 全面解析Go語(yǔ)言中crypto/sha1庫(kù)

    全面解析Go語(yǔ)言中crypto/sha1庫(kù)

    crypto/sha1在Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)中是一個(gè)強(qiáng)大且實(shí)用的工具,適用于多種應(yīng)用場(chǎng)景,本文就詳細(xì)的介紹了Go語(yǔ)言中crypto/sha1庫(kù),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • 深入解析Golang中JSON的編碼與解碼

    深入解析Golang中JSON的編碼與解碼

    隨著互聯(lián)網(wǎng)的快速發(fā)展和數(shù)據(jù)交換的廣泛應(yīng)用,各種數(shù)據(jù)格式的處理成為軟件開(kāi)發(fā)中的關(guān)鍵問(wèn)題,本文將介紹?Golang?中?JSON?編碼與解碼的相關(guān)知識(shí),幫助大家了解其基本原理和高效應(yīng)用,需要的可以收藏一下
    2023-05-05
  • Go?for-range?的?value值地址每次都一樣的原因解析

    Go?for-range?的?value值地址每次都一樣的原因解析

    循環(huán)語(yǔ)句是一種常用的控制結(jié)構(gòu),在?Go?語(yǔ)言中,除了?for?關(guān)鍵字以外,還有一個(gè)?range?關(guān)鍵字,可以使用?for-range?循環(huán)迭代數(shù)組、切片、字符串、map?和?channel?這些數(shù)據(jù)類型,這篇文章主要介紹了Go?for-range?的?value值地址每次都一樣的原因解析,需要的朋友可以參考下
    2023-05-05
  • Go語(yǔ)言基礎(chǔ)go fmt命令使用示例詳解

    Go語(yǔ)言基礎(chǔ)go fmt命令使用示例詳解

    這篇文章主要為大家介紹了Go語(yǔ)言基礎(chǔ)go fmt命令的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-11-11

最新評(píng)論