This is all possible and quite neat to dive into the specifics, but if you really want to be able swap a std lib call, just turn it into a variable and change it.
// code.go
var now = time.Now
// code_test.go
func TestCode(t *testing.T) {
nowSwap := now
t.Cleanup (func() {
now = nowSwap
}
now = func() time.Time {
return time.Date(...)
}
}
Examples
Code: https://github.com/open-telemetry/opentelemetry-go/blob/main...
Test: https://github.com/open-telemetry/opentelemetry-go/blob/490f...That is a useful pattern, though I was unclear on why `t.Cleanup` and not `defer`. In case others are curious, too:
> Parallel subtestsWith t.Run(..., func(t testing.T) { t.Parallel(); ... }), the parent test function can return (and thus run its defers) before parallel subtests actually finish.*
The point of the OP is that it changes calls to `time.Now` regardless of whether the code that's calling it uses your variable or not.
I suspect that using a build tag (say `test`) and two function definitions (one that directly calls `time.Now()` and one test-only one that uses a mutable var) will optimize out to zero cost in the non-test case - last I fiddled with that, it was pretty good at consistently inlining trivial wrapper funcs like that.
Other prior art: https://github.com/bouk/monkey with accompanying blog post https://bou.ke/blog/monkey-patching-in-go/
Yikes, I don't see any legitimate use for this, other than hacking for the sake of hacking. Interesting read though.
Hot reloading for development loops is _the_ canonical use case for this.
wdym, now it will be possible to implement Wordpress in Go
Well, we are on Hacker News after all...