Skip to content

Commit 1d58b5a

Browse files
authored
Merge pull request #802 from devlights/add-replace-timenow-with-golinkname-directive
2 parents 0daa585 + 801b8fe commit 1d58b5a

File tree

4 files changed

+89
-0
lines changed

4 files changed

+89
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
app
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# これは何?
2+
3+
[go:linknameコンパイラディレクティブ](https://pkg.go.dev/cmd/compile#hdr-Compiler_Directives) を利用して
4+
5+
```time.Now()``` を置き換えるサンプルです。参考情報に上げているサイトの記事がとても勉強になりました。
6+
7+
実行すると以下のようになります。
8+
9+
```sh
10+
$ task
11+
task: [build] go build -o app
12+
task: [default] ./app
13+
2000-01-01 00:00:00 +0000 UTC
14+
```
15+
16+
```time.Now()``` の結果を固定日時になるように置き換えているので、どのタイミングでtime.Now()を呼んでも同じ日時となります。
17+
18+
## 参考情報
19+
20+
- https://www.sobyte.net/post/2022-07/go-linkname/
21+
- https://zenn.dev/sasakiki/articles/a838380540245d
22+
- https://pkg.go.dev/cmd/compile#hdr-Compiler_Directives
23+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# https://taskfile.dev
2+
3+
version: "3"
4+
5+
tasks:
6+
default:
7+
cmds:
8+
- task: build
9+
- ./app
10+
build:
11+
cmds:
12+
- go build -o app
13+
clean:
14+
cmds:
15+
- rm -f ./app
16+
doc:
17+
cmds:
18+
- go doc -cmd -u -all .
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"time"
6+
_ "unsafe"
7+
)
8+
9+
// fixedNow は、固定の時間を返す time.Now() のモックです。
10+
//
11+
// 標準ライブラリの time.Now() を置き換えるために
12+
// linknameコンパイラディレクティブを付与しています。
13+
//
14+
// linknameコンパイラディレクティブを利用するためには
15+
// unsafeパッケージをインポート(明示的、暗黙的問わず)する必要があります。
16+
//
17+
// linknameは、標準ライブラリ内で利用されており、例えば time.Sleep() も
18+
// 実際のソースコードを見ると以下の宣言となっており、宣言のみで実装がありません。
19+
//
20+
// # $(go env GOROOT)/src/time/sleep.go
21+
//
22+
// package time
23+
//
24+
// func Sleep(d Duration)
25+
//
26+
// 実体は、runtime.timeSleep() となっています。
27+
//
28+
// # $(go env GOROOT)/src/runtime/time.go
29+
//
30+
// package runtime
31+
//
32+
// //go:linkname timeSleep time.Sleep
33+
// func timeSleep(ns int64) { ... }
34+
//
35+
//go:linkname fixedNow time.Now
36+
func fixedNow() time.Time {
37+
return time.Date(2000, 1, 1, 0, 0, 0, 0, time.Local)
38+
}
39+
40+
func init() {
41+
log.SetFlags(0)
42+
}
43+
44+
func main() {
45+
// linknameコンパイラディレクティブによって time.Now が置き換えられる
46+
log.Println(time.Now())
47+
}

0 commit comments

Comments
 (0)