関連記事
GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ
概要
以下、自分用のメモです。忘れないようにここにメモメモ。。。
標準ライブラリの time.Sleep()
ってどんな実装になってるんだろうって思ってソース見てみたら
// 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)
https://cs.opensource.google/go/go/+/refs/tags/go1.22.3:src/time/sleep.go;l=9
ん?実装が無い。。?なんで?ってなりました。
んで、情報を探すと以下を発見。
回答を見ると、実際には runtime
パッケージの方に定義されているよとのこと。
てことで、src/runtime/time.go
というファイルを見てみると
// timeSleep puts the current goroutine to sleep for at least ns nanoseconds. // //go:linkname timeSleep time.Sleep func timeSleep(ns int64) {
https://cs.opensource.google/go/go/+/refs/tags/go1.22.3:src/runtime/time.go;l=178
あった。よく見ると go:linkname
というディレティブが付いている。
これは何だ?って調べると以下のとても分かりやすい説明をしてくださっている記事がありました。感謝。
なるほど・・・。既存関数を置き換えられるのですね。当然安全ではないので、しょっちゅう利用するものでは無い。
でも、知っておくとイザというときに役に立ちそう。
以下、自分用で試してみたサンプルです。上のzennの記事で用いられているサンプルほぼそのままとなりましたが。
サンプル
package main import ( "log" "time" _ "unsafe" ) // fixedNow は、固定の時間を返す time.Now() のモックです。 // // 標準ライブラリの time.Now() を置き換えるために // linknameコンパイラディレクティブを付与しています。 // // linknameコンパイラディレクティブを利用するためには // unsafeパッケージをインポート(明示的、暗黙的問わず)する必要があります。 // // linknameは、標準ライブラリ内で利用されており、例えば time.Sleep() も // 実際のソースコードを見ると以下の宣言となっており、宣言のみで実装がありません。 // // # $(go env GOROOT)/src/time/sleep.go // // package time // // func Sleep(d Duration) // // 実体は、runtime.timeSleep() となっています。 // // # $(go env GOROOT)/src/runtime/time.go // // package runtime // // //go:linkname timeSleep time.Sleep // func timeSleep(ns int64) { ... } // //go:linkname fixedNow time.Now func fixedNow() time.Time { return time.Date(2000, 1, 1, 0, 0, 0, 0, time.Local) } func init() { log.SetFlags(0) } func main() { // linknameコンパイラディレクティブによって time.Now が置き換えられる log.Println(time.Now()) }
実行すると以下のようになります。
$ task task: [build] go build -o app task: [default] ./app 2000-01-01 00:00:00 +0000 UTC
time.Now()
の結果を固定日時になるように置き換えているので、どのタイミングでtime.Now()を呼んでも同じ日時となります。
参考情報
- https://www.sobyte.net/post/2022-07/go-linkname/
- https://zenn.dev/sasakiki/articles/a838380540245d
- https://pkg.go.dev/cmd/compile#hdr-Compiler_Directives
- https://forum.golangbridge.org/t/implementation-of-time-sleep/2637
Goのおすすめ書籍
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。