比较 Goroutines 中的时间

Comparing times in Goroutines

我有一个用 Go 编写的测试:

func TestThings(t *testing.T) {
    tCh := make(chan int64, 10000)
    ctx, cx := context.WithTimeout(context.Background(), 20*time.Second)
    defer cx()

    wg := sync.WaitGroup{}
    wg.Add(2)
    go func(c context.Context) {
        defer wg.Done()
        defer close(tCh)
        for {
            select {
            case <-c.Done():
                return
            default:
                nt := time.Now()
                tCh <- nt.UnixNano()
            }
        }
    }(ctx)

    go func(c context.Context) {
        defer wg.Done()
        for {
            select {
            case <-c.Done():
                return
            default:
                v := <-tCh
                nt := time.Now()
                res := nt.UnixNano() - v
                if res < 0 {
                    t.Errorf("got less than 0; diff: %d now: %d then: %d", res, nt.UnixNano(), v)
                }
            }
        }
    }(ctx)
    wg.Wait()
}

运行 这个测试(有时)以结果结束:

go test -v -run TestThings ./test
=== RUN   TestThings
    test.go:48: got less than 0; diff: -33686100 now: 1639183246323013700 then: 1639183246356699800
    test.go:48: got less than 0; diff: -33535000 now: 1639183246323171300 then: 1639183246356706300
    test.go:48: got less than 0; diff: -33490200 now: 1639183246323222600 then: 1639183246356712800
    test.go:48: got less than 0; diff: -33488300 now: 1639183246323231000 then: 1639183246356719300
    test.go:48: got less than 0; diff: -33502600 now: 1639183246323241000 then: 1639183246356743600
    test.go:48: got less than 0; diff: -33551600 now: 1639183246323249100 then: 1639183246356800700
         ...
--- FAIL: TestThings (20.01s)
FAIL
FAIL    test 20.022s
FAIL

为什么接收Goroutine的时间有时早于发送Goroutine的时间?

我知道当涉及到计算机时,时钟通常是硬的和不可靠的,但我希望因为这些 Goroutines(也许?)在同一个进程中,但肯定在同一个主机上,调用 time.Now() 会 return 不断增加价值。或者至少不是“早期”的。

更新:

其他可能值得一提的事情:我 运行 在 Macbook Pro 上的 VSCode devcontainer 中。

正如@Peter 对引用 time package docs 的原始问题所评论的那样,time.Time 的序列化在设计上丢失了任何单调信息:

Because the monotonic clock reading has no meaning outside the current process, the serialized forms generated by t.GobEncode, t.MarshalBinary, t.MarshalJSON, and t.MarshalText omit the monotonic clock reading, and t.Format provides no format for it. Similarly, the constructors time.Date, time.Parse, time.ParseInLocation, and time.Unix, as well as the unmarshalers t.GobDecode, t.UnmarshalBinary. t.UnmarshalJSON, and t.UnmarshalText always create times with no monotonic clock reading.

将原始问题中的代码片段更改为在 Goroutine 之间传递 time.Time 值没有问题。