タイムアウト(キャンセル)を context.Context に寄せてみる
気が向いたので前書いた go のライブラリの一つのタイムアウトの指定(キャンセルも含む)を context.Context に寄せてみた。 (https://github.com/soh335/test-mysqld-docker/pull/6) このライブラリは docker で test 用の mysqld のプロセスを管理するもの。
NewMysqld()
を呼ぶとタイムアウトするまで docker で mysql を立てて、ピングが通ったら dsn を知ることができるという流れになっている。
今までは config struct に timeout の指定を入れて渡していた。こんな感じ。( nil だった時はこの config の値をデフォルトで指定してたけど)
config := &MysqldConfig{ Tag: "mysql:latest", Timeout: 30 } mysqld, err := mysqltest.NewMysqld(config) if err != nil { log.Fatal(err.Error()) } defer mysqld.Stop() db, err := sql.Open("mysql", mysqld.DSN()) ...
それを context に寄せて見たものがこれ。
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) defer cancel() mysqld, err := mysqltest.NewMysqld(ctx, "mysql:latest") if err != nil { log.Fatal(err.Error()) } defer mysqld.Stop() db, err := sql.Open("mysql", mysqld.DSN()) ...
config の内容が tag しかなくなってしまったので、string として渡すようにした。
個人的には defer を二つ書かないといけないのがちょっと見栄えが良くないな…と感じた。ドキュメントとか関数名次第であると思うけど、直感的に cancel がここでいう NewMysqld だけに効くのか Stop にも効くのか分かりづらいなぁという感じ。大抵 context を渡すのって何かの操作一つだからかな。 そういう意味では、NewMysqld より Start とかの方が context が効く範囲がわかりやすいかも?
まぁ内部だけで使うにしても、標準ライブラリも context に色々対応してきたし使った方が楽なことが多いので、使っていきたいとこ。