Back to Timetable
Goと一緒に育つCLI — 9年のOSS保守で見た標準ライブラリとtestingの進化
標準入力を受け取り、チャットサービスへ通知する小さなGo製CLIを、約9年にわたって保守してきました。 この発表では、そのCLIの実装と変更履歴を題材に、Go本体・標準ライブラリ・testingの進化が、小さなCLIの設計と保守をどのように変えてきたかを紹介します。 初期の実装では、goroutine、channel、timer、signal handlingを手組みし、非同期処理のテストも `runtime.GOMAXPROCS(1)` や短い `time.Sleep` に頼っていました。また、ホームディレクトリ取得やエラーのwrapなど、今では標準ライブラリで自然に書ける処理にも外部パッケージを使っていました。 そこから、`os.UserHomeDir`、Go 1.13のerror wrapping、`signal.NotifyContext`、`context.WithoutCancel`、`T.Setenv`、`T.Context()`、そして `testing/synctest` へと移り変わる中で、コードは少しずつ「外部依存や偶然に頼るもの」から「Goの標準機能で意図を表現できるもの」へ変わっていきました。 特に中心に置くのは、非同期処理のテストです。かつてはruntime schedulerの挙動に依存していたテストが、`testing/synctest` によって、goroutineの停止状態を明示的に待てるテストへ変わった過程を、実際のコードの変遷をもとに紹介します。 Goの互換性と標準ライブラリの継続的な進化は、大きなプロダクトだけでなく、個人が長く保守する小さなCLIにも届いています。この発表では、ひとつのツールを9年保守してきた経験を通じて、Goと一緒に遠くまで進むとはどういうことかを具体的に示します。 ## 参加者が得られるもの * goroutine / channel / timerを含むCLI処理のテスト設計 * `runtime.GOMAXPROCS(1)` や `time.Sleep` に頼る非同期テストの問題点 * `testing/synctest` による非同期テストの改善例 * `signal.NotifyContext` を使ったCLI shutdown設計 * `context.WithoutCancel` を使うべき場面と、timeoutを戻す注意点 * `os.UserHomeDir` やGo 1.13 error wrappingなど、標準ライブラリの進化による外部依存削減 * `T.Setenv` / `T.TempDir` / `T.Context()` などによるテスト保守性の改善 * 小さなOSSや社内ツールを、Goの進化に合わせて長く保守していく考え方 ## 対象者 * GoでCLIや小さなツールを書いている人 * goroutine / channel / context を使った処理のテストに悩んだことがある人 * 社内ツールやOSSを長く保守している、またはこれから保守していきたい人 * Goの標準ライブラリやtestingの進化を、実例ベースで知りたい人 ## 対象レベル **中級者** goroutine、channel、context、testingの基本を知っていると理解しやすい内容です。 ただし、個別のAPIは背景から説明するため、CLIやテスト改善に関心がある初級者にも役立つ構成にします。
Tatsuya Kaneko Tatsuya Kaneko

株式会社PR TIMES CTO

ISUCON本の著者の1人。ISUCON練習用の https://github.com/catatsuy/private-isu など、数々のOSSを作成・メンテナンスを行っている。Podcast「八百万のOSS」で、OSSの設計・実装・運用を深掘りしている。