Problem: You want to measure the lapsed time and make sure that it is accurate.
Solution: Use the monotonic clock in the Time struct to find the lapsed time.
The Time struct contains the data but only under certain circumstances. If you create a Time struct instance using time.Now , and print out the struct, you will be able to see the monotonic clock:
t := time.Now()
fmt.Println(t)
When you run it you see this:
2023-10-24 18:54:04.771816477 +0800 CST m=+0.000021017
The m=+0.000021017 part is the monotonic clock. The part before that is the wall clock. This is what the package documentation says:
If the time has a monotonic clock reading, the returned string includes a final field “m=±<value>”, where value is the monotonic clock reading formatted as a decimal number of seconds.
But what does it mean by the monotonic clock reading formatted as a decimal number of seconds ? It’s a really small number! Actually, this just shows how long your program has been running.
func main() { time.Sleep(10 * time.Second) // pretend to do something for 10s t1 := time.Now() t2 := time.Now() fmt.Println("t1:", t1) fmt.Println("t2:", t2) fmt.Println("difference:", t2.Sub(t1)) }
This is what you should see after 10 seconds:
zzh@ZZHPC:/zdata/MyPrograms/Go/study$ go run main.go t1: 2023-10-24 18:59:01.682946905 +0800 CST m=+10.007175697 t2: 2023-10-24 18:59:01.682946973 +0800 CST m=+10.007175764 difference: 67ns
The interesting point to note here is that if you use the wall clock, you won’t be able to tell the difference at all!
As noted earlier, the monotonic clock data is not always available in the Time struct. Methods such as AddDate , Round , and Truncate are wall clock computations so the Time structs they return won’t have the monotonic clock. Similarly, In, Local , and UTC interpret the wall clock, so the Time structs they return won’t have the monotonic clock either.
You can also remove the monotonic clock yourself. Just use the Round method with a 0 parameter:
func main() { t := time.Now().Round(0) fmt.Println(t) }
You should get something like this:
zzh@ZZHPC:/zdata/MyPrograms/Go/study$ go run main.go 2023-10-24 19:02:01.311982287 +0800 CST
You no longer see the monotonic clock here. So what happens when you try to call Sub (or any other monotonic methods) on a Time struct instance that doesn’t have the monotonic clock?
func main() { t1r := time.Now().Round(0) t2r := time.Now().Round(0) t3r := time.Now().Round(time.Second) t4r := time.Now().Round(time.Second) t1t := time.Now().Truncate(0) t2t := time.Now().Truncate(0) t3t := time.Now().Truncate(time.Second) t4t := time.Now().Truncate(time.Second) t5t := time.Now().Truncate(time.Millisecond) t6t := time.Now().Truncate(time.Millisecond) t7t := time.Now().Truncate(time.Microsecond) t8t := time.Now().Truncate(time.Microsecond) t9t := time.Now().Truncate(time.Nanosecond) t10t := time.Now().Truncate(time.Nanosecond) fmt.Println("t1r:", t1r) fmt.Println("t2r:", t2r) fmt.Println("t3r:", t3r) fmt.Println("t4r:", t4r) fmt.Println("t1t:", t1t) fmt.Println("t2t:", t2t) fmt.Println("t3t:", t3t) fmt.Println("t4t:", t4t) fmt.Println("t5t:", t5t) fmt.Println("t6t:", t6t) fmt.Println("t7t:", t7t) fmt.Println("t8t:", t8t) fmt.Println("t9t:", t9t) fmt.Println("t10t:", t10t) fmt.Println("difference between t1t and t2t:", t2t.Sub(t1t)) fmt.Println("difference between t3t and t4t:", t4t.Sub(t3t)) fmt.Println("difference between t5t and t6t:", t6t.Sub(t5t)) fmt.Println("difference between t7t and t8t:", t8t.Sub(t7t)) fmt.Println("difference between t9t and t10t:", t10t.Sub(t9t)) }
Now t1 and t2 have their monotonic clocks stripped away. If you try to find the difference between these two times, you will get a big fat 0. This is because the operation will be done on the wall clock instead of the monotonic clock, and the wall clock just isn’t fine-grained enough:
zzh@ZZHPC:/zdata/Github/ztest$ go run main.go t1r: 2024-03-10 21:03:38.833227187 +0800 CST t2r: 2024-03-10 21:03:38.833227258 +0800 CST t3r: 2024-03-10 21:03:39 +0800 CST t4r: 2024-03-10 21:03:39 +0800 CST t1t: 2024-03-10 21:03:38.833227667 +0800 CST t2t: 2024-03-10 21:03:38.833227729 +0800 CST t3t: 2024-03-10 21:03:38 +0800 CST t4t: 2024-03-10 21:03:38 +0800 CST t5t: 2024-03-10 21:03:38.833 +0800 CST t6t: 2024-03-10 21:03:38.833 +0800 CST t7t: 2024-03-10 21:03:38.833228 +0800 CST t8t: 2024-03-10 21:03:38.833228 +0800 CST t9t: 2024-03-10 21:03:38.833228194 +0800 CST t10t: 2024-03-10 21:03:38.833228252 +0800 CST difference between t1t and t2t: 62ns difference between t3t and t4t: 0s difference between t5t and t6t: 0s difference between t7t and t8t: 0s difference between t9t and t10t: 58ns