Golang中如何使用自启动以来的单调时钟

Golang中如何使用自启动以来的单调时钟 大家好,

我正在开发一个专门用于在不同传感器之间进行测量的Go语言代码。每个传感器都有自己的代码,我希望能够在板上实现一个统一的计时基准。所有传感器都由一个树莓派管理。因此,我需要一个非常精确的时钟,为不同的代码提供一个共同的起始点。过去我使用C++开发这些代码时,使用的是steady_clock(链接),它是一个单调且精确的时钟(微秒级),从系统启动开始计时。现在我正在使用Go语言进行开发,正在寻找一个等效的方法。你们知道如何实现吗?

提前感谢!!


更多关于Golang中如何使用自启动以来的单调时钟的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang中如何使用自启动以来的单调时钟的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中,你可以使用time.Since(bootTime)结合系统启动时间来实现类似C++ steady_clock的功能。以下是具体实现:

package main

import (
    "fmt"
    "time"
    "syscall"
)

var bootTime time.Time

func init() {
    // 获取系统启动时间(Linux系统)
    var sysinfo syscall.Sysinfo_t
    err := syscall.Sysinfo(&sysinfo)
    if err != nil {
        panic(err)
    }
    bootTime = time.Now().Add(-time.Duration(sysinfo.Uptime) * time.Second)
}

// MonotonicClock 返回自系统启动以来的单调时间
func MonotonicClock() time.Duration {
    return time.Since(bootTime)
}

func main() {
    // 示例:获取自启动以来的精确时间
    t1 := MonotonicClock()
    time.Sleep(100 * time.Millisecond)
    t2 := MonotonicClock()
    
    fmt.Printf("启动后时间1: %v\n", t1)
    fmt.Printf("启动后时间2: %v\n", t2)
    fmt.Printf("时间差: %v\n", t2-t1)
    
    // 微秒级精度输出
    fmt.Printf("时间差(微秒): %d μs\n", (t2-t1).Microseconds())
}

对于需要更高精度和跨平台兼容性的情况,可以使用runtime.nanotime()

package main

import (
    "fmt"
    "time"
    "unsafe"
)

//go:linkname nanotime runtime.nanotime
func nanotime() int64

func MonotonicNanoseconds() int64 {
    return nanotime()
}

func main() {
    start := MonotonicNanoseconds()
    time.Sleep(150 * time.Microsecond)
    end := MonotonicNanoseconds()
    
    elapsed := end - start
    fmt.Printf("耗时: %d ns\n", elapsed)
    fmt.Printf("耗时: %.3f μs\n", float64(elapsed)/1000)
}

如果你需要与C++ steady_clock完全相同的纳秒级单调时钟,可以使用cgo调用系统时钟:

package main

/*
#include <time.h>

static long long steady_clock_ns() {
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return (long long)ts.tv_sec * 1000000000LL + (long long)ts.tv_nsec;
}
*/
import "C"
import "fmt"

func SteadyClock() int64 {
    return int64(C.steady_clock_ns())
}

func main() {
    t1 := SteadyClock()
    // 模拟工作负载
    for i := 0; i < 1000; i++ {}
    t2 := SteadyClock()
    
    fmt.Printf("CLOCK_MONOTONIC时间: %d ns\n", t2-t1)
}

第一种方法适合大多数应用场景,精度在微秒级。第二种方法提供了纳秒级精度但需要Go的内部链接。第三种方法通过cgo直接调用系统CLOCK_MONOTONIC,与C++的steady_clock行为完全一致。

回到顶部