Help us understand the problem. What is going on with this article?

golangでnet.ConnのRead・Writeをcontextでcancel可能にする方法

モチベーション

ソケットから読もうとするとブロックする可能性があるので、
それをcontextでキャンセルできる様にしたい。

可能なら以下の様なコードが書きたいが、それはできないので、代替案をメモ

select {
case size, err := conn.Read():
// 略
case <-ctx.Done():
//略
}

解決策

こんな感じでSetDeadlineを使うと良い。
なお、デッドラインの設定時間により、ctx.Done() への応答時間が伸びたりするが、
Readへの応答時間要求に比べてctx.Done()への応答時間要求はかなりゆるい場合が多いと思うので問題になることは少ないはず。

continue_read := true
for continue_read {
    err := conn.SetReadDeadline(time.Now().Add(time.Millisecond * 500))
    if err != nil {
        return err
    }

    size, err := conn.Read(buf)
    switch {
    case err == nil || os.IsTimeout(err):
        continue_read = true  // Do nothing
    case errors.Is(err, io.EOF):
        continue_read = false
    default:
        return err
    }

    // bufの操作等を書く


    select {
    case <-ctx.Done():
        return ctx.Err()
    default:
    }
}

うーん、一応問題は解決したものの、あんまり綺麗じゃないので何とかしたい。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away