go - ZeroMQを使用してGoで割り込みを処理する慣用的な方法

go interrupt zeromq

私は現在GoとZeroMQの両方を学んでおり、その精神の中で私はZguideのGoの例に貢献しようとしています。 interrupt exampleで少し苦労しています。問題を処理する慣用的な方法が何であるかわかりません。

私が現在持っている解決策は次のとおりです。SIGINT信号を受信するチャネルを作成します。そうなったとき、メインループで使用される別のチャネルにブール値を書き込みます。問題は、Recvがブロックしているため、ループがループ状態をチェックできないことです。 NOBLOCK定数をRecvに渡すことで問題を回避しています。しかし、Recvが中断されたときにEINTRを返す必要があるため、より良い方法があると感じています(これは、私の知る限りではありません)。あなたの読者はこの質問に答えるのにはるかによく備えています、私は、あなたはどう思いますか?

あなたの便宜のために私がこれまでに持っているコード:

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.\n", string(msgbytes))
      }
    }

}


編集はフィードバックに基づいてコードを多少簡略化しました
答え
selectステートメントを使用してチャネルを切り替える場合は、チャネルでのsocket.Recvの結果も返す必要があります。これにより、goroutineでsocket.Recvを実行することもできるため、ブロッキングの性質は問題になりません。

現実的には、おそらく発生したエラーも処理する必要があります。シバン全体に別のチャンネルを追加することでできること。

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.\n", string(msgbytes))
      }
    }

}
関連記事

websocket - Golangを使用したクロスオリジンWebソケット

xml - Goの要素の任意のXML属性をマーシャルしますか?

map - goでのマップの型変換

inheritance - 別の形式でインターフェースを実装する

memory - Go:マップキーを再利用する場合のメモリ使用量の増加

google-app-engine - GAE Goとロングポーリング?

python - Google App EngineでCoffeescriptを使用する方法

go - ほとんどのメソッドで単一の型がレシーバーになるGoでサブパッケージを含むパッケージを適切に構成するにはどうすればよいですか?

google-app-engine - GAE Go Json-RPC呼び出しの例

arm - Goツールは間違ったアーキテクチャ用にビルドされていますか?