タイムテーブル 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やテスト改善に関心がある初級者にも役立つ構成にします。
株式会社PR TIMES CTO
ISUCON本の著者の1人。ISUCON練習用の https://github.com/catatsuy/private-isu など、数々のOSSを作成・メンテナンスを行っている。Podcast「八百万のOSS」で、OSSの設計・実装・運用を深掘りしている。