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

golang控制結構select機制及使用示例詳解

 更新時間:2023年10月15日 08:56:00   作者:TimLiu  
這篇文章主要介紹了golang控制結構select機制及使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

GO select

在 Go 語言中,select 是一種用于處理多個通道操作的控制結構。它可以用于在多個通道之間進行非阻塞的選擇操作。

select 語句由一系列的 case 子句組成,每個 case 子句表示一個通道操作。select 語句會按照順序依次檢查每個 case 子句,并執(zhí)行其中可執(zhí)行的操作。

select 的作用主要有以下幾個方面:

多路復用通道

select 可以同時監(jiān)聽多個通道上的操作,一旦某個通道可讀或可寫,就會執(zhí)行相應的操作。這樣可以避免使用阻塞的 channel 操作,提高程序的并發(fā)性能。

package main
import (
    "fmt"
    "time"
)
func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)
    go func() {
        time.Sleep(2 * time.Second)
        ch1 <- 1
    }()
    go func() {
        time.Sleep(1 * time.Second)
        ch2 <- 2
    }()
    select {
    case <-ch1:
        fmt.Println("Received from ch1")
    case <-ch2:
        fmt.Println("Received from ch2")
    case <-time.After(3 * time.Second):
        fmt.Println("Timeout")
    }
}

在這個示例中,我們創(chuàng)建了兩個通道 ch1 和 ch2。然后分別在兩個 goroutine 中進行操作,通過不同的延遲時間向通道發(fā)送數(shù)據(jù)。

在 main 函數(shù)中,我們使用 select 語句同時監(jiān)聽 ch1 和 ch2 兩個通道,并通過 <-ch1 和 <-ch2 分別接收通道中的數(shù)據(jù)。同時,我們還使用 time.After 函數(shù)設置了一個 3 秒的超時時間。

在 select 語句的執(zhí)行過程中,會依次檢查每個 case 子句。如果有多個 case 子句都是可執(zhí)行的,select 會隨機選擇一個執(zhí)行。在這個示例中,由于 ch2 的數(shù)據(jù)發(fā)送時間比 ch1 早,所以最終會執(zhí)行 case <-ch2 分支,輸出 "Received from ch2"。

如果 select 語句中的所有通道都沒有數(shù)據(jù)可讀,并且超過了設置的超時時間,那么就會執(zhí)行 time.After 對應的 case 分支,輸出 "Timeout"。

非阻塞的通道操作

select 語句中的 case 子句可以使用非阻塞的通道操作,包括發(fā)送和接收操作。如果沒有可用的通道操作,select 會立即執(zhí)行 default 子句(如果有),或者阻塞等待第一個可執(zhí)行的操作。

package main
import (
    "fmt"
)
func main() {
    ch := make(chan int, 2)
    ch <- 1 // 向通道寫入數(shù)據(jù),此時通道未滿,操作不會被阻塞
    fmt.Println("Data written to channel")
    select {
    case ch <- 2: // 嘗試向已滿的通道再次寫入數(shù)據(jù),由于通道已滿,操作會被立即返回
        fmt.Println("Data written to channel")
    default:
        fmt.Println("Channel is full, unable to write data")
    }
    data, ok := <-ch // 嘗試從通道讀取數(shù)據(jù),此時通道中有數(shù)據(jù),操作不會被阻塞
    if ok {
        fmt.Println("Data read from channel:", data)
    }
    select {
    case data, ok := <-ch: // 嘗試從空的通道讀取數(shù)據(jù),由于通道為空,操作會被立即返回
        if ok {
            fmt.Println("Data read from channel:", data)
        } else {
            fmt.Println("Channel is empty, unable to read data")
        }
    default:
        fmt.Println("Channel is empty, unable to read data")
    }
}

在這個示例中,我們首先創(chuàng)建了一個緩沖大小為 2 的通道 ch。然后,我們使用帶緩沖的通道進行數(shù)據(jù)寫入操作 ch <- 1,由于通道未滿,操作不會被阻塞。

接下來,我們使用非阻塞的通道寫入操作 ch <- 2,由于通道已滿,操作會立即返回。我們使用 select 語句來處理這種情況,當無法進行通道寫入操作時,會執(zhí)行 default 分支,輸出 "Channel is full, unable to write data"。

然后,我們嘗試從通道中讀取數(shù)據(jù) data, ok := <-ch,由于通道中有數(shù)據(jù),操作不會被阻塞。

最后,我們使用非阻塞的通道讀取操作 data, ok := <-ch,由于通道為空,操作會立即返回。同樣,我們使用 select 語句來處理這種情況,當無法進行通道讀取操作時,會執(zhí)行 default 分支,輸出 "Channel is empty, unable to read data"。

超時處理

通過在 select 語句中結合使用 time.After 函數(shù)和通道操作,可以實現(xiàn)超時機制。例如,可以使用 select 監(jiān)聽一個帶有超時的通道操作,當超過指定時間時,執(zhí)行相應的操作。

package main
import (
    "fmt"
    "time"
)
func main() {
    ch := make(chan int)
    go func() {
        time.Sleep(2 * time.Second)
        ch <- 1
    }()
    select {
    case <-ch:
        fmt.Println("Received from channel")
    case <-time.After(3 * time.Second):
        fmt.Println("Timeout")
    }
}

在這個示例中,我們創(chuàng)建了一個通道 ch。然后,我們在一個 goroutine 中進行操作,在 2 秒后向通道發(fā)送數(shù)據(jù) ch <- 1

在 main 函數(shù)中,我們使用 select 語句同時監(jiān)聽 ch 通道和 time.After 函數(shù)返回的超時通道。超時通道是一個計時器通道,在指定的時間后會發(fā)送一個值給通道。

在 select 語句的執(zhí)行過程中,會依次檢查每個 case 子句。如果 ch 通道接收到了數(shù)據(jù),就會執(zhí)行 case <-ch 分支,輸出 "Received from channel"。如果等待時間超過了設定的超時時間(這里是 3 秒),就會執(zhí)行 time.After 對應的 case 分支,輸出 "Timeout"。

在這個示例中,由于通道的發(fā)送操作需要 2 秒才能完成,而超時時間設定為 3 秒,所以最終會執(zhí)行 case <-ch 分支,輸出 "Received from channel"。

控制并發(fā)流程

select 可以與 goroutine 結合使用,實現(xiàn)對并發(fā)流程的控制。通過在 select 中使用通道操作來進行同步或通信,可以協(xié)調(diào)不同 goroutine 之間的執(zhí)行順序。

package main
import (
    "fmt"
    "sync"
)
func main() {
    var wg sync.WaitGroup
    // 設置并發(fā)任務數(shù)量
    concurrency := 3
    // 創(chuàng)建一個用于控制并發(fā)的通道
    semaphore := make(chan struct{}, concurrency)
    // 假設有一組任務需要并發(fā)執(zhí)行
    tasks := []string{"task1", "task2", "task3", "task4", "task5"}
    // 遍歷任務列表
    for _, task := range tasks {
        // 增加 WaitGroup 的計數(shù)器
        wg.Add(1)
        // 啟動一個 goroutine 來執(zhí)行任務
        go func(t string) {
            // 在 goroutine 開始前向通道發(fā)送一個信號
            semaphore <- struct{}{}
            // 執(zhí)行任務
            fmt.Println("Executing", t)
            // 模擬任務執(zhí)行時間
            // 這里可以是任何實際的任務邏輯
            // ...
            // 任務完成后從通道釋放一個信號
            <-semaphore
            // 減少 WaitGroup 的計數(shù)器
            wg.Done()
        }(task)
    }
    // 等待所有任務完成
    wg.Wait()
    fmt.Println("All tasks completed")
}

在這個示例中,我們首先定義了并發(fā)任務的數(shù)量 concurrency,這決定了同時執(zhí)行任務的最大數(shù)量。然后,我們創(chuàng)建了一個用于控制并發(fā)的通道 semaphore,通過向通道發(fā)送信號來控制并發(fā)數(shù)量。

接下來,我們定義了一組需要并發(fā)執(zhí)行的任務列表 tasks。在遍歷任務列表時,我們增加了 WaitGroup 的計數(shù)器,并啟動一個 goroutine 來執(zhí)行每個任務。

在每個任務的 goroutine 中,首先向通道 semaphore 發(fā)送一個信號,以占用一個并發(fā)槽位。然后執(zhí)行任務的邏輯,這里使用了簡單的輸出來表示任務的執(zhí)行。任務執(zhí)行完畢后,從通道 semaphore 中釋放一個信號,以讓其他任務可以占用并發(fā)槽位。最后,減少 WaitGroup 的計數(shù)器,表示任務完成。

最后,我們使用 WaitGroup 的 Wait 方法來等待所有任務完成,確保程序在所有任務執(zhí)行完畢后再繼續(xù)執(zhí)行。

總結

以下是 select 語句的一些特性:

  • 如果沒有任何通道操作準備好,且沒有默認的 case 子句,那么 select 語句會被阻塞,直到至少有一個通道操作準備好。
  • 如果有多個 case 子句準備好,那么會隨機選擇一個執(zhí)行。不會有優(yōu)先級或順序的保證。
  • select 語句可以用于發(fā)送和接收操作,也可以混合使用。
  • select 語句可以與 for 循環(huán)結合使用,以實現(xiàn)對多個通道的連續(xù)監(jiān)控和處理。

select 機制是 Golang 中處理并發(fā)操作的重要工具之一,它能夠很好地處理多個通道操作,避免阻塞和死鎖的問題。

以上就是golang控制結構select機制使用示例詳解的詳細內(nèi)容,更多關于golang select機制的資料請關注腳本之家其它相關文章!

相關文章

  • 詳解Golang如何實現(xiàn)支持隨機刪除元素的堆

    詳解Golang如何實現(xiàn)支持隨機刪除元素的堆

    堆是一種非常常用的數(shù)據(jù)結構,它能夠支持在O(1)的時間復雜度獲取到最大值(或最小值)。本文主要介紹了如何實現(xiàn)支持O(log(n))隨機刪除元素的堆,需要的可以參考一下
    2022-09-09
  • go語言channel實現(xiàn)多核并行化運行的方法

    go語言channel實現(xiàn)多核并行化運行的方法

    這篇文章主要介紹了go語言channel實現(xiàn)多核并行化運行的方法,實例分析了channel實現(xiàn)多核并行化運行的技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-03-03
  • Go并發(fā)4種方法簡明講解

    Go并發(fā)4種方法簡明講解

    這篇文章主要介紹了Go并發(fā)4種方法簡明講解,需要的朋友可以參考下
    2022-04-04
  • golang 語言中錯誤處理機制

    golang 語言中錯誤處理機制

    Golang 的錯誤處理方式可能和這些你熟悉的語言有所不同,今天通過本文給大家分享golang 語言中錯誤處理機制,感興趣的朋友一起看看吧
    2021-08-08
  • Go并發(fā)控制Channel使用場景分析

    Go并發(fā)控制Channel使用場景分析

    使用channel來控制子協(xié)程的優(yōu)點是實現(xiàn)簡單,缺點是當需要大量創(chuàng)建協(xié)程時就需要有相同數(shù)量的channel,而且對于子協(xié)程繼續(xù)派生出來的協(xié)程不方便控制
    2021-07-07
  • go語言算法題解二叉樹的拷貝、鏡像和對稱

    go語言算法題解二叉樹的拷貝、鏡像和對稱

    這篇文章主要為大家詳細介紹了go語言算法題解二叉樹的拷貝、鏡像和對稱,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-01-01
  • go?generate代碼自動生成指南

    go?generate代碼自動生成指南

    這篇文章主要介紹了go?generate代碼自動生成指南,本文將探討?go?generate?命令的使用方法、原理以及一些實際應用場景,希望讀者能夠更好地理解和運用這個強大的工具
    2024-01-01
  • golang中字符串和數(shù)字轉換方法

    golang中字符串和數(shù)字轉換方法

    在Golang中,可以使用strconv包中的Itoa()和Atoi()函數(shù)進行字符串與數(shù)字之間的轉換,Itoa()用于將數(shù)字轉換為字符串,Atoi()則用于將字符串轉換回數(shù)字,本文介紹golang中字符串和數(shù)字轉換方法,感興趣的朋友一起看看吧
    2024-09-09
  • GO語言并發(fā)之好用的sync包詳解

    GO語言并發(fā)之好用的sync包詳解

    標準庫中的sync包在我們的日常開發(fā)中用的頗為廣泛,那么大家對sync包的用法知道多少呢,這篇文章就大致講一下sync包和它的使用,感興趣的可以學習一下
    2022-12-12
  • 詳解Golang如何實現(xiàn)節(jié)假日不打擾用戶

    詳解Golang如何實現(xiàn)節(jié)假日不打擾用戶

    這篇文章主要為大家介紹了Golang如何實現(xiàn)節(jié)假日不打擾用戶過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01

最新評論