Go 如何实现对无缓冲通道的非阻塞写入?

Go 如何实现对无缓冲通道的非阻塞写入?,go,channel,Go,Channel,从 接收器总是阻塞,直到有数据要接收。如果通道无缓冲,发送方将阻塞,直到接收方收到该值 但将信号中继到无缓冲通道而不阻塞。这是如何工作的,是否可能与其他chan一起工作当它说os时意味着什么。Notify不会阻止是指如果它阻止,消息将被丢弃。因此,虽然它确实不会阻塞,但如果不能立即接收到信号,它就不会中继信号。这可以通过简单的选择来完成: select { case channel <- message: // message sent default:

接收器总是阻塞,直到有数据要接收。如果通道无缓冲,发送方将阻塞,直到接收方收到该值


但将信号中继到无缓冲通道而不阻塞。这是如何工作的,是否可能与其他chan一起工作当它说
os时意味着什么。Notify
不会阻止是指如果它阻止,消息将被丢弃。因此,虽然它确实不会阻塞,但如果不能立即接收到信号,它就不会中继信号。这可以通过简单的
选择来完成:

select {
    case channel <- message:
        // message sent
    default:
        // message dropped
}
选择{

case channel在(可能)仍然通过使用另一个goroutine保证交付时,您始终可以避免阻塞:

go func() { channel <- message }()
go func(){channel
这就是为什么Notify的文档明确指出应该使用缓冲通道的原因

使用,也将使这一点更加清楚:

呼叫信号的新警告。在无缓冲通道上通知
vet
工具现在警告呼叫
signal.Notify
,将传入信号发送到无缓冲通道

使用无缓冲通道可能会丢失作为
信号发送的信号。发送到通道时,Notify
不会阻塞

例如:

c:=make(转换操作信号)
//在读取通道之前,信号通过c发送。
//当c未缓冲时,该信号可能被丢弃。
信号通知(c,操作系统中断)
signal.Notify的用户应使用具有足够缓冲空间的频道,以跟上预期的信号速率


啊,好吧。陷入了使用select从频道读取的习惯中——没有考虑太多。我现在看到了。顺便说一句,这种带有默认大小写的select样式可以用于在频道可能被关闭多次的情况下安全关闭频道(因为关闭关闭的频道会导致恐慌).Example:。如果频道关闭可以同时运行,但是,您需要使用互斥锁来保护它:@Kaedys,这不是必需的。只需使用
sync。一旦
。挑剔:这个频道和阻塞的goroutine不会在内存中(直到程序结束),如果没有人碰巧从通道中读取?这是正确的。与缓冲通道相比,一个主要的缺点是,如果goroutine被阻止,并且没有其他人引用它,它将不会被垃圾收集。我的建议只是一个简单的方法,可以避免在未缓冲的通道上进行阻止,同时最大限度地提高仍然传递的机会他在传递信息。