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

Golang關(guān)鍵字select的常用用法總結(jié)

 更新時(shí)間:2023年10月26日 09:58:56   作者:林欣快滾去學(xué)習(xí)  
這篇文章主要為大家詳細(xì)介紹了golang中select關(guān)鍵字的常用用法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

一、Select解決什么問(wèn)題

在Golang中,兩個(gè)協(xié)程之間通信Channel(圖一),在接受協(xié)程中通過(guò)代碼表示即為<ch;如果協(xié)程需要監(jiān)聽(tīng)多個(gè)Channel,只要有其中一個(gè)滿足條件,就執(zhí)行相應(yīng)的邏輯(圖二),這種select的應(yīng)用場(chǎng)景之一,代碼如下:

func TestSelect(t *testing.T) {
    ch1 := make(chan int, 1)
    ch2 := make(chan int , 1)

    select {
        case <-ch1:
        fmt.Println("ch1")
        case <-ch2:
        fmt.Println("ch2")
        default:
        }
}

上述代碼,創(chuàng)建兩個(gè)通道,通過(guò)select監(jiān)聽(tīng)協(xié)程是否有數(shù)據(jù),如果有打印相應(yīng)的值,如果沒(méi)有通過(guò)default結(jié)束程序運(yùn)行;

二、Select常用用法

循環(huán)阻塞監(jiān)測(cè)

func TestLoopSelect(t *testing.T) {
    ch1 := make(chan int, 1)
    ch2 := make(chan int, 1)

    go func() {
        // 每隔1s發(fā)送一條消息到channel中
        for range time.Tick(1 * time.Second) {
            ch1 <- 1
        }
    }()

    for {
        select {
            case <-ch1:
            fmt.Println("ch1")
            case <-ch2:
            fmt.Println("ch2")
        }
    }
}

這種寫(xiě)法特別常見(jiàn),起一個(gè)協(xié)程,阻塞循環(huán)監(jiān)聽(tīng)多個(gè)channel,如果有數(shù)據(jù)執(zhí)行對(duì)應(yīng)的操作。比如說(shuō)

// go-zero/core/discov/internal/registry.go
func (c *cluster) watchStream(cli EtcdClient, key string, rev int64) bool {
    var rch clientv3.WatchChan
    if rev != 0 {
        rch = cli.Watch(clientv3.WithRequireLeader(c.context(cli)), makeKeyPrefix(key), clientv3.WithPrefix(),
                      clientv3.WithRev(rev+1))
    } else {
        rch = cli.Watch(clientv3.WithRequireLeader(c.context(cli)), makeKeyPrefix(key), clientv3.WithPrefix())
    }

    for {
        select {
            case wresp, ok := <-rch:
        	...
            c.handleWatchEvents(key, wresp.Events)
            case <-c.done:
            return true
        }
    }
}

上述代碼,通過(guò)for + select阻塞循環(huán)監(jiān)測(cè)注冊(cè)中心數(shù)據(jù)是否有變換,有變化的話,針對(duì)變化類(lèi)型,執(zhí)行對(duì)應(yīng)邏輯;

非阻塞監(jiān)控

func TestSelect(t *testing.T) {
    ch1 := make(chan int, 1)
    ch2 := make(chan int , 1)

    select {
        case <-ch1:
        fmt.Println("ch1")
        case <-ch2:
        fmt.Println("ch2")
        default:
        }
}

這段代碼的意思是,程序執(zhí)行到select,就檢查一下channel里面是否有數(shù)據(jù),有就處理,沒(méi)有就退出;在grpc-go中,

// grpc-go/clientconn.go
func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *ClientConn, err error) {
	cc := &ClientConn{
		target: target,
		conns:  make(map[*addrConn]struct{}),
		dopts:  defaultDialOptions(),
		czData: new(channelzData),
	}

	defer func() {
		select {
		case <-ctx.Done():
			switch {
			case ctx.Err() == err:
				conn = nil
			case err == nil || !cc.dopts.returnLastError:
				conn, err = nil, ctx.Err()
			default:
				conn, err = nil, fmt.Errorf("%v: %v", ctx.Err(), err)
			}
		default:
		}
	}()

	if cc.dopts.scChan != nil {
		// Blocking wait for the initial service config.
		select {
		case sc, ok := <-cc.dopts.scChan:
			if ok {
				cc.sc = &sc
				cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{&sc})
			}
		case <-ctx.Done():
			return nil, ctx.Err()
		}
	}

}

上述代碼中,有兩個(gè)地方用到select,一個(gè)地方是非阻塞,檢查contex是否被取消;另外一個(gè)是阻塞等待;

三、select原理

如果想了解select的實(shí)現(xiàn),可以閱讀runtime.selectgo代碼。它主要包含三部分:

首先,檢查一下是否有準(zhǔn)備就緒的channel(多個(gè)channel就緒,隨機(jī)選擇一個(gè)),如果有,就執(zhí)行;

其次,將當(dāng)前goroutine包裝成sudog,掛載到對(duì)應(yīng)的channel上;

最后,如果channel中數(shù)據(jù)準(zhǔn)備就緒,喚醒該協(xié)程繼續(xù)執(zhí)行第一步邏輯;

【注】源碼細(xì)節(jié),感興趣并且有需求可以深入了解,但是不要陷入源碼的怪圈中;

總結(jié)

本文主要講述下面三部分內(nèi)容:

  • 從Go源碼開(kāi)發(fā)者的角度考慮,為什么需要select?
  • 介紹了select常用的兩種寫(xiě)法,一種是非阻塞的,一種是阻塞的,以及開(kāi)源項(xiàng)目如何使用它們;
  • 介紹了select的基本實(shí)現(xiàn);

以上就是Golang關(guān)鍵字select的常用用法總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于go select的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • go使用Gin框架利用阿里云實(shí)現(xiàn)短信驗(yàn)證碼功能

    go使用Gin框架利用阿里云實(shí)現(xiàn)短信驗(yàn)證碼功能

    這篇文章主要介紹了go使用Gin框架利用阿里云實(shí)現(xiàn)短信驗(yàn)證碼,使用json配置文件及配置文件解析,編寫(xiě)路由controller層,本文通過(guò)代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2021-08-08
  • Go語(yǔ)言基礎(chǔ)切片的創(chuàng)建及初始化示例詳解

    Go語(yǔ)言基礎(chǔ)切片的創(chuàng)建及初始化示例詳解

    這篇文章主要為大家介紹了Go語(yǔ)言基礎(chǔ)切片的創(chuàng)建及初始化示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2021-11-11
  • Golang通道的無(wú)阻塞讀寫(xiě)的方法示例

    Golang通道的無(wú)阻塞讀寫(xiě)的方法示例

    這篇文章主要介紹了Golang通道的無(wú)阻塞讀寫(xiě)的方法示例,詳細(xì)的介紹了哪些情況會(huì)存在阻塞,以及如何使用select解決阻塞,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-11-11
  • go mod更新指定的tag的包后,go vendor內(nèi)容未更新問(wèn)題

    go mod更新指定的tag的包后,go vendor內(nèi)容未更新問(wèn)題

    這篇文章主要介紹了go mod更新指定的tag的包后,go vendor內(nèi)容未更新問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 一文帶你掌握Golang中panic與recover的使用方法

    一文帶你掌握Golang中panic與recover的使用方法

    這篇文章主要介紹了Golang中panic與recover的作用和使用方法,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,需要的小伙伴可以參考一下
    2023-04-04
  • 使用Go實(shí)現(xiàn)在命令行輸出好看的表格

    使用Go實(shí)現(xiàn)在命令行輸出好看的表格

    這篇文章主要介紹了使用Go實(shí)現(xiàn)在命令行輸出好看的表格方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • golang中實(shí)現(xiàn)graphql請(qǐng)求的方法

    golang中實(shí)現(xiàn)graphql請(qǐng)求的方法

    這篇文章主要介紹了如何在golang中實(shí)現(xiàn)graphql請(qǐng)求,在本文中,我們介紹了如何使用gqlgen來(lái)構(gòu)建GraphQL服務(wù),需要的朋友可以參考下
    2023-04-04
  • golang log4go的日志輸出優(yōu)化詳解

    golang log4go的日志輸出優(yōu)化詳解

    log4go源于google的一項(xiàng)log工程,但官方已經(jīng)停止維護(hù)更新,下面這篇文章主要給大家介紹了關(guān)于golang log4go的日志輸出優(yōu)化的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-12-12
  • golang?beego框架路由ORM增刪改查完整案例

    golang?beego框架路由ORM增刪改查完整案例

    這篇文章主要為大家介紹了golang?beego框架路由ORM增刪改查完整案例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • Go語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之希爾排序示例詳解

    Go語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之希爾排序示例詳解

    這篇文章主要為大家介紹了Go語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之希爾排序示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08

最新評(píng)論