dongma2388 2012-06-18 10:12
浏览 102
已采纳

使用ZeroMQ在Go中处理中断的惯用方式

I'm learning both Go and ZeroMQ at the moment and in that spirit I'm trying to contribute Go examples for the Zguide. I'm struggling a bit with the interrupt example. I'm unsure what the idiomatic way of handling the problem would be.

The solution I currently have is the following: I create a channel which receives the SIGINT signal. When it does I write a bool on an other channel which is used in the main loop to break. The problem is, is that Recv is blocking, the loop never gets to check the loop condition. I circumvent the problem by passing the NOBLOCK constant to Recv. But I feel there is a better way as Recv should return a EINTR when interrupted (which it doesn't as far as I can tell). You readers are much better equipped to answer this question then I am, what do you think?

For your convenience the code I have so far:

package main

import (
    "os/signal"
    "os"
    "fmt"
    zmq "github.com/alecthomas/gozmq"
)

func listenForSignals(exit_channel chan bool) {
    signal_channel := make(chan os.Signal)
    signal.Notify(signal_channel)
    <- signal_channel
    fmt.Println("stopping")
    exit_channel <- true
}

func main() {
    exit := make(chan bool)
    exit_signal := false
    go listenForSignals(exit)

    context, _ := zmq.NewContext()
    defer context.Close()

    socket, _ := context.NewSocket(zmq.REP)
    defer socket.Close()
    socket.Bind("tcp://*:5555")

    for exit_signal == false {
      select {
      case exit_signal = <- exit:
        fmt.Println("W: interrupt received, killing server...")
      default:
        msgbytes, err := socket.Recv(zmq.NOBLOCK)
        fmt.Printf("%s.
", string(msgbytes))
      }
    }

}

Edit simplified the code somewhat based on feedback

  • 写回答

2条回答 默认 最新

  • dongxindu8753 2012-07-02 18:45
    关注

    If you are going to use a select statement to switch over channels, you should return the result of socket.Recv on a channel as well. This also lets you run socket.Recv on a goroutine so the blocking nature isn't an issue.

    Realistically, you should probably also handle errors that you get as well. That you can do by adding another channel to the whole shebang.

    func main() {
        ...
    
        data := make(chan []byte)
        errors := make(chan error)
        go function() {
          for {
            msgbytes, err := socket.Recv(0)
            if err != nil {
              errors <- err
            } else {
              data <- msgbytes
            }
          }
        }()
    
        for exit_signal == false {
          select {
          case exit_signal = <- exit:
            fmt.Println("W: interrupt received, killing server...")
          case err := <- errors:
            fmt.Println("Receive Error:", err.Error())
          case msgbytes := <- data:
            fmt.Printf("%s.
    ", string(msgbytes))
          }
        }
    
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 wegame打不开英雄联盟
  • ¥15 公司的电脑,win10系统自带远程协助,访问家里个人电脑,提示出现内部错误,各种常规的设置都已经尝试,感觉公司对此功能进行了限制(我们是集团公司)
  • ¥15 救!ENVI5.6深度学习初始化模型报错怎么办?
  • ¥30 eclipse开启服务后,网页无法打开
  • ¥30 雷达辐射源信号参考模型
  • ¥15 html+css+js如何实现这样子的效果?
  • ¥15 STM32单片机自主设计
  • ¥15 如何在node.js中或者java中给wav格式的音频编码成sil格式呢
  • ¥15 不小心不正规的开发公司导致不给我们y码,
  • ¥15 我的代码无法在vc++中运行呀,错误很多