##モチベーション
ソケットから読もうとするとブロックする可能性があるので、
それを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:
}
}
うーん、一応問題は解決したものの、あんまり綺麗じゃないので何とかしたい。