簡體   English   中英

如何在不等待另一個 goroutine 中設置的情況下讀取通道?

[英]How to read channel without waiting setting in another goroutine?

我在 goroutine 中使用 channel 有問題。

var test = make(chan string)

func main() {
    go initChan()

    for i := 0; i < 2; i++ {
        go readChan()
    }

    var input string
    fmt.Scanln(&input)
}

func initChan() {
    for i := 0; i < 100; i++ {
        test <- "Iteration num: " + strconv.Itoa(i)
        time.Sleep(time.Second * 5)
    }
}

func readChan() {
    for {
        message := <- test
        log.Println(message)
    }
}

輸出:

2019/12/24 08:21:17 Iteration num: 0
2019/12/24 08:21:22 Iteration num: 1
2019/12/24 08:21:27 Iteration num: 2
2019/12/24 08:21:32 Iteration num: 3
2019/12/24 08:21:37 Iteration num: 4
2019/12/24 08:21:42 Iteration num: 5
................................

我需要線程讀取而無需等待測試變量的更新。 現在每個 readChan() 都在等待 initChan() 更新測試變量。

是否可以讓 readChan() 線程一次性工作而無需為每個線程等待 initChan()?

創建了一個惡魔,它將所有消息從測試通道推送到所有其他監聽程序。

var test = make(chan string)

var mapChan = make(map[int]chan string)
var count = 3

func main() {
    go initChan()
    go deamon()
    for i := 0; i < count; i++ {
        mapChan[i] = make(chan string)
        go readChan(i)
    }

    var input string
    fmt.Scanln(&input)
}

func deamon() {
    for {
        message := <-test
        for i := 0; i < count; i++ {
            mapChan[i] <- message
        }
    }
}

func initChan() {
    for i := 0; i < 100; i++ {
        test <- "Iteration num: " + strconv.Itoa(i)
        time.Sleep(time.Second * 1)
    }
}

func readChan(i int) {
    for {
        select {

        case message := <-mapChan[i]:
            log.Println(message)
        default:
            // Do for not when written on channel
        }
    }
}

如果我正確理解您的問題,此解決方案可能會有所幫助。 我使用了一個大小為 1 的緩沖通道,因此作為發送方的 goroutine 永遠不會被阻塞,這是在無緩沖通道的情況下。 您可以閱讀有關頻道的更多信息:頻道行為

package main

import (
    "log"
    "strconv"
    "sync"
    "time"
)

// Buffered channel with size 1 guarantees delayed delivery of data
// As soon as the goroutine sends to the channel, the reciever goroutine dequeus it
// Then the reciver goroutines does the work, but the sender goroutine isn't blocked
// As the size is again 0 after the reciever recieved it but might haven't processed it yet
var test = make(chan string, 1)

func main() {
    var wg sync.WaitGroup
    wg.Add(2)
    // Waits for other goroutines to complete before the main goroutine returns
    defer wg.Wait()
    go initChan(&wg)
    go readChan(&wg)
}

func initChan(wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 100; i++ {
        // Sends continuously
        test <- "Iteration num: " + strconv.Itoa(i)
        time.Sleep(time.Second * 5)
    }
    close(test)
}

func readChan(wg *sync.WaitGroup) {
    defer wg.Done()
    var message string
    var ok bool
    // Reciever deques the value as soon as it recieves it
    // But might take time to proceed
    for {
        select {
        case message, ok = <-test:
            // If channel is closed
            if ok == false {
                return
            }
            log.Println(message)
        default:
            log.Println(message)
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM