登录
首页 >  Golang >  Go问答

如何在不阅读的情况下检查频道是否关闭?

来源:Golang技术栈

时间:2023-04-17 12:58:32 139浏览 收藏

IT行业相对于一般传统行业,发展更新速度更快,一旦停止了学习,很快就会被行业所淘汰。所以我们需要踏踏实实的不断学习,精进自己的技术,尤其是初学者。今天golang学习网给大家整理了《如何在不阅读的情况下检查频道是否关闭?》,聊聊golang,我们一起来看看吧!

问题内容

这是@Jimt 编写的Go 中worker 和controller 模式的一个很好的例子,以回答“Golang 中是否有一些优雅的方式来暂停和恢复任何其他goroutine? ”

package main

import (
    "fmt"
    "runtime"
    "sync"
    "time"
)

// Possible worker states.
const (
    Stopped = 0
    Paused  = 1
    Running = 2
)

// Maximum number of workers.
const WorkerCount = 1000

func main() {
    // Launch workers.
    var wg sync.WaitGroup
    wg.Add(WorkerCount + 1)

    workers := make([]chan int, WorkerCount)
    for i := range workers {
        workers[i] = make(chan int)

        go func(i int) {
            worker(i, workers[i])
            wg.Done()
        }(i)
    }

    // Launch controller routine.
    go func() {
        controller(workers)
        wg.Done()
    }()

    // Wait for all goroutines to finish.
    wg.Wait()
}

func worker(id int, ws 

但是这段代码也有一个问题:如果你想在退出workers时删除一个工作通道worker(),就会发生死锁。

如果你close(workers[i]),下次控制器写入它会导致恐慌,因为 go 无法写入关闭的通道。如果您使用一些互斥锁来保护它,那么它将被卡住,workers[i] 因为worker它没有从通道读取任何内容并且写入将被阻塞,并且互斥锁将导致死锁。您还可以为通道提供更大的缓冲区作为解决方法,但这还不够好。

所以我认为解决这个问题的最好方法是worker()退出时关闭通道,如果控制器发现通道关闭,它将跳过它并且什么都不做。但是在这种情况下,我找不到如何检查通道是否已关闭。如果我尝试读取控制器中的通道,控制器可能被阻塞。所以我现在很困惑。

PS:恢复引发的恐慌是我尝试过的,但它会关闭引发恐慌的goroutine。在这种情况下,它将是控制器,所以没有用。

不过,我认为 Go 团队在下一个版本的 Go 中实现这个功能是有用的。

正确答案

可以通过一种 hacky 方式,通过恢复引发的恐慌来尝试写入的通道。但是如果不读取读取通道,则无法检查它是否已关闭。

要么你会

  • 最终从中读取“真实”值 ( v )
  • 读取“真”值和“未关闭”指示符 ( v, ok )
  • 读取 零值 和“关闭”指示器 ( v, ok )(示例
  • 将阻塞在永久读取的通道中 ( v )

只有最后一个在技术上不会从频道中读取,但这没什么用。

今天关于《如何在不阅读的情况下检查频道是否关闭?》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于golang的内容请关注golang学习网公众号!

声明:本文转载于:Golang技术栈 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>