如何终止阻塞的 Go 协程

huangapple go评论76阅读模式
英文:

How to kill blocking go routine

问题

所以我正在尝试实现一个Go协程,它简单地监听Redis订阅(我使用Go-redis库进行此操作),然后在接收/处理Redis消息后,在通道上发送消息。

类似这样的代码:

func foo(redis *redis.Client, comm chan HandlerSignal) {

    ...

    for {
        msg, err := pubsub.ReceiveMessage()
        sig := HandlerSignal{msg}
        comm <- sig
    }
}

但是我无法找到告诉Go协程在阻塞并等待Redis消息时返回的最佳方法。

有人知道这种情况下的常见做法吗?还是我完全错了?

英文:

So i'm trying to implement a go routine that simply listens on a Redis subscription (I use the Go-redis library for this) and then sends messages
on a channel after it recieves/processes the redis messages.

Something like this:

func foo(redis *redis.Client, comm chan HandlerSignal) {

    ...

    for {
        msg, err := pubsub.ReceiveMessage()
        sig := HandlerSignal{msg}
        comm &lt;- sig
    }
}

But I can't figure out the best way to tell the go routine to return when it is blocking and waiting for a redis message.

Does anyone know the common practice for this kind of situation or am I going about this all wrong?

答案1

得分: 2

根据我在这里看到的:https://github.com/go-redis/redis/blob/v3.2.30/pubsub.go#L253 pubsub.ReceiveMessage() 在内部使用了 ReceiveTimeout(5 * time.Second)。为什么不使用相同的函数(就像 @Tomasz Kłak 建议的那样)?

func foo(redis *redis.Client, comm chan HandlerSignal, quit chan struct{}) {
    ...
    for {
        
        select {
        case <-quit:
            return
        default:
            msg, err := pubsub.ReceiveTimeout(5 * time.Second)
            sig := HandlerSignal{msg}
            comm <- sig    
        }
    }
}

由于 ReceiveTimeout 会阻塞程序执行 5 秒钟,所以默认情况下不会被执行。

英文:

As I can see here: https://github.com/go-redis/redis/blob/v3.2.30/pubsub.go#L253 pubsub.ReceiveMessage() uses internally ReceiveTimeout(5 * time.Second). Why not use the same function (as @Tomasz Kłak suggested)?

func foo(redis *redis.Client, comm chan HandlerSignal, quit chan struct{}) {
    ...
    for {
        
        select {
        case &lt;-quit:
            return
        default:
            msg, err := pubsub.ReceiveTimeout(5 * time.Second)
            sig := HandlerSignal{msg}
            comm &lt;- sig    
        }
    }
}

Since ReceiveTimeout will block routine for the following 5 seconds, default case will be not saturated.

huangapple
  • 本文由 发表于 2016年2月20日 00:52:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/35510557.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定