如何在不等待另一个 goroutine 中设置的情况下读取频道?

我在 goroutine 中使用通道时遇到问题。


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() ?


一只萌萌小番薯
浏览 126回答 2
2回答

冉冉说

创建了一个恶魔,它将所有消息从测试通道推送到所有其他监听程序。var test = make(chan string)var mapChan = make(map[int]chan string)var count = 3func main() {&nbsp; &nbsp; go initChan()&nbsp; &nbsp; go deamon()&nbsp; &nbsp; for i := 0; i < count; i++ {&nbsp; &nbsp; &nbsp; &nbsp; mapChan[i] = make(chan string)&nbsp; &nbsp; &nbsp; &nbsp; go readChan(i)&nbsp; &nbsp; }&nbsp; &nbsp; var input string&nbsp; &nbsp; fmt.Scanln(&input)}func deamon() {&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; message := <-test&nbsp; &nbsp; &nbsp; &nbsp; for i := 0; i < count; i++ {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mapChan[i] <- message&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}func initChan() {&nbsp; &nbsp; for i := 0; i < 100; i++ {&nbsp; &nbsp; &nbsp; &nbsp; test <- "Iteration num: " + strconv.Itoa(i)&nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(time.Second * 1)&nbsp; &nbsp; }}func readChan(i int) {&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case message := <-mapChan[i]:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Println(message)&nbsp; &nbsp; &nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Do for not when written on channel&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}

陪伴而非守候

如果我正确理解您的问题,此解决方案可能会有所帮助。我使用了一个大小为 1 的缓冲通道,因此作为发送方的 goroutine 永远不会被阻塞,这是在无缓冲通道的情况下。您可以阅读有关频道的更多信息:频道的行为package mainimport (&nbsp; &nbsp; "log"&nbsp; &nbsp; "strconv"&nbsp; &nbsp; "sync"&nbsp; &nbsp; "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 yetvar test = make(chan string, 1)func main() {&nbsp; &nbsp; var wg sync.WaitGroup&nbsp; &nbsp; wg.Add(2)&nbsp; &nbsp; // Waits for other goroutines to complete before the main goroutine returns&nbsp; &nbsp; defer wg.Wait()&nbsp; &nbsp; go initChan(&wg)&nbsp; &nbsp; go readChan(&wg)}func initChan(wg *sync.WaitGroup) {&nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; for i := 0; i < 100; i++ {&nbsp; &nbsp; &nbsp; &nbsp; // Sends continuously&nbsp; &nbsp; &nbsp; &nbsp; test <- "Iteration num: " + strconv.Itoa(i)&nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(time.Second * 5)&nbsp; &nbsp; }&nbsp; &nbsp; close(test)}func readChan(wg *sync.WaitGroup) {&nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; var message string&nbsp; &nbsp; var ok bool&nbsp; &nbsp; // Reciever deques the value as soon as it recieves it&nbsp; &nbsp; // But might take time to proceed&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case message, ok = <-test:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // If channel is closed&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ok == false {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Println(message)&nbsp; &nbsp; &nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Println(message)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go