[インデックス 17410] ファイルの概要
このコミットは、Go言語の time
パッケージにおける Sleep
関数のドキュメントを改善するものです。具体的には、Sleep
が指定された期間「少なくとも」一時停止すること、および負の値やゼロの期間を渡した場合の挙動について、より明確な説明を追加しています。
コミット
commit 8159b6901f0f18f213897f27d5bd4806c3e18ee2
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Wed Aug 28 11:16:55 2013 -0700
time: add more docs on Sleep
Merge the comment from runtime/time.goc ("at least")
and also note that negative is okay and won't crash.
I see people going out of their way to avoid passing
a negative value to Sleep.
R=golang-dev, adg, r, alex.brainman
CC=golang-dev
https://golang.org/cl/13271045
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/8159b6901f0f18f213897f27d5bd4806c3e18ee2
元コミット内容
time: add more docs on Sleep
Merge the comment from runtime/time.goc ("at least")
and also note that negative is okay and won't crash.
I see people going out of their way to avoid passing
a negative value to Sleep.
変更の背景
このコミットの背景には、Go言語の time.Sleep
関数の挙動に関する開発者の誤解や不明瞭さがありました。特に以下の点が問題視されていました。
- 「少なくとも」の保証の不明瞭さ:
Sleep
関数は指定された期間だけ正確にスリープするわけではなく、「少なくとも」その期間スリープすることを保証します。これはスケジューラの特性やシステム負荷によって、実際のスリープ時間が指定された期間よりも長くなる可能性があるためです。しかし、この重要なニュアンスがドキュメントに明記されていませんでした。 - 負の値やゼロの期間の扱い: 多くのプログラミング言語やAPIでは、時間に関連する関数に負の値を渡すとエラーになったり、未定義の挙動を引き起こしたりすることがあります。そのため、Goの開発者も
time.Sleep
に負のDuration
を渡すことを避けようとする傾向がありました。しかし、GoのSleep
関数は負の値やゼロのDuration
を渡してもクラッシュせず、即座にリターンするという明確な挙動を持っていました。この挙動がドキュメントに明記されていなかったため、不必要な回避策が講じられることがありました。
コミットメッセージにある I see people going out of their way to avoid passing a negative value to Sleep.
という記述は、このような誤解が実際に存在し、開発者が不必要なコードを書いている現状を示しています。このコミットは、これらの誤解を解消し、Sleep
関数の正しい挙動を明確にすることで、開発者の生産性を向上させることを目的としています。
前提知識の解説
このコミットを理解するためには、以下のGo言語の基本的な概念と time
パッケージに関する知識が必要です。
- Goroutine (ゴルーチン): Go言語における軽量な実行スレッドです。Goランタイムによって管理され、OSのスレッドに多重化されて実行されます。
time.Sleep
は特定のゴルーチンを一時停止させます。 - Goスケジューラ: Goランタイムの一部であり、ゴルーチンをOSスレッドにマッピングし、実行を管理します。
time.Sleep
が指定された期間「少なくとも」一時停止するのは、このスケジューラが他のゴルーチンにCPU時間を割り当てたり、OSがスレッドをスケジューリングしたりするオーバーヘッドがあるためです。 time.Duration
型: Go言語のtime
パッケージで定義されている、時間の長さを表す型です。int64
のエイリアスであり、ナノ秒単位で時間を表現します。例えば、time.Second
は1秒を表すDuration
定数です。Duration
は負の値も取り得ます。time.Sleep
関数:func Sleep(d Duration)
というシグネチャを持つ関数で、現在のゴルーチンを指定された期間d
だけ一時停止させます。
これらの知識があることで、Sleep
関数のドキュメントの変更がなぜ重要なのか、そしてその変更がどのような意味を持つのかを深く理解できます。特に、Sleep
が「少なくとも」一時停止するという点は、リアルタイムシステムや厳密なタイミングが要求されるアプリケーションを開発する際に非常に重要になります。
技術的詳細
このコミットは、src/pkg/time/sleep.go
ファイル内の Sleep
関数のコメントを修正することで、その挙動に関するドキュメントを改善しています。
変更前:
// Sleep pauses the current goroutine for the duration d.
func Sleep(d Duration)
変更後:
// Sleep pauses the current goroutine for at least the duration d.
// A negative or zero duration causes Sleep to return immediately.
func Sleep(d Duration)
この変更は、以下の2つの重要な情報を追加しています。
-
for at least the duration d
(少なくとも期間d): これはSleep
関数の最も重要な特性の一つです。Goのスケジューラは、指定された期間が経過した後にゴルーチンをすぐに再開することを保証しません。スケジューラの負荷、他のゴルーチンの実行状況、OSのスケジューリングポリシーなど、様々な要因によって、実際の再開は指定された期間よりも遅れる可能性があります。したがって、Sleep
は「少なくとも」指定された期間だけ一時停止することを保証するものであり、正確な期間を保証するものではありません。この文言の追加により、開発者はSleep
を使用する際にこの非決定性を考慮に入れる必要性が明確になります。 -
A negative or zero duration causes Sleep to return immediately.
(負またはゼロの期間はSleepを即座に返す): これは、Duration
が負の値やゼロであった場合のSleep
の挙動を明確にしています。多くのプログラミング言語では、このような入力はエラーを引き起こす可能性がありますが、GoのSleep
はエラーを発生させず、単に現在のゴルーチンを一時停止することなく即座に処理を続行します。この挙動は、例えば計算結果が負になる可能性がある場合に、if d <= 0 { return }
のような明示的なチェックを不要にし、コードを簡潔に保つことができます。この情報が明記されたことで、開発者は安心して負の値やゼロをSleep
に渡すことができるようになり、不必要なガード句を記述する手間が省けます。
このドキュメントの変更は、Sleep
関数の内部実装を変更するものではなく、あくまでその外部から見える挙動に関する説明を改善するものです。しかし、これにより開発者が Sleep
をより正確に理解し、適切に使用できるようになるため、Goプログラムの堅牢性と可読性の向上に寄与します。
コアとなるコードの変更箇所
--- a/src/pkg/time/sleep.go
+++ b/src/pkg/time/sleep.go
@@ -4,7 +4,8 @@
package time
-// Sleep pauses the current goroutine for the duration d.
+// Sleep pauses the current goroutine for at least the duration d.
+// A negative or zero duration causes Sleep to return immediately.
func Sleep(d Duration)
func nano() int64 {
コアとなるコードの解説
変更は src/pkg/time/sleep.go
ファイル内の Sleep
関数の関数宣言直前のコメントブロックにあります。
元のコメント:
// Sleep pauses the current goroutine for the duration d.
これは Sleep
が現在のゴルーチンを指定された期間 d
だけ一時停止させるという基本的な機能のみを説明していました。
変更後のコメント:
// Sleep pauses the current goroutine for at least the duration d.
// A negative or zero duration causes Sleep to return immediately.
1行目の変更 (for at least
) は、Sleep
が指定された期間よりも長く一時停止する可能性があるという、Goスケジューラの特性に起因する重要な保証を明確にしています。これは、Sleep
が厳密なリアルタイムタイマーではないことを示唆しています。
2行目の追加は、d
が負の値またはゼロの場合の Sleep
の挙動を明示しています。この場合、Sleep
は一時停止せずに即座に制御を呼び出し元に戻します。これは、Duration
が計算によって負になる可能性があるシナリオにおいて、開発者が不必要なエラーハンドリングや条件分岐を記述するのを避けるのに役立ちます。
この変更は、Sleep
関数のシグネチャや内部実装(func nano() int64
や runtime_beforeExit()
など、コメントブロックの下にある実際の関数本体)には一切影響を与えていません。純粋にドキュメントの改善であり、関数の利用者がその挙動をより正確に理解できるようにするためのものです。
関連リンク
- Go言語の
time
パッケージのドキュメント: https://pkg.go.dev/time (現在の最新ドキュメント) - Go言語のスケジューラに関する情報: Goのランタイムスケジューラは、Goの並行処理モデルの核心であり、ゴルーチンの効率的な実行を可能にします。詳細については、Goの公式ドキュメントや関連するブログ記事を参照してください。
参考にした情報源リンク
- Go言語の公式ドキュメント (
time
パッケージ): https://pkg.go.dev/time - Goのコミット履歴: https://github.com/golang/go/commits/master
- Go CL (Change List) 13271045: https://golang.org/cl/13271045 (このコミットに対応するGoのコードレビューシステム上の変更リスト)
time.Sleep
の挙動に関する一般的な議論 (例: Stack Overflow, Goコミュニティのフォーラムなど)- "golang time.Sleep negative duration" で検索すると、このコミットの背景にある開発者の疑問や誤解に関する議論が見られます。例えば、Stack Overflowの質問「What happens if time.Sleep is called with a negative duration?」などが参考になります。
- https://stackoverflow.com/questions/17906735/what-happens-if-time-sleep-is-called-with-a-negative-duration