Go语言相同时刻不同Location实例的time对象==比较失败问题
问题原因
这是Go语言time.Time类型的比较规则和内部结构共同导致的,核心逻辑如下:
- Go里对结构体使用
==做比较时,会逐个对比所有字段的值,只要有一个字段不相等,最终结果就是false。而指针类型字段的相等判断,只看两个指针是否指向同一个内存地址,不会关心指针指向的内容是否完全一致。 time.Time结构体内部持有一个*time.Location类型的指针字段,用来记录时间关联的时区实例。当你用==对比两个时间对象时,会直接对比这个时区指针的地址值。- 你测试中出现false结果,本质是因为两个时间对象里存的时区指针指向了不同的
Location实例——哪怕这两个实例的时区名、时区偏移规则完全一模一样,只要内存地址不同,==比较就会判定这部分字段不相等,最终返回false。
补充说明:标准库的
time.LoadLocation本身对同名时区做了全局缓存,常规场景下两次调用相同时区名会返回同一个指针实例。但不管是缓存未命中、还是手动通过time.FixedZone等方式构造了内容相同但地址不同的时区实例,都不改变==对比指针地址的核心逻辑。
注意:Go官方从来没有推荐过用==判断两个时间是否代表同一时刻,==会同时对比时间的墙钟值、单调时钟值、时区指针三个部分,很容易出现“两个时间代表同一时刻但==返回false”的情况。
正确写法
判断两个时间是否为同一时刻,始终使用time.Time提供的Equal()方法,该方法会自动忽略时区实例、单调时钟的差异,只对比两个时间对应的实际UTC时间点:
package main import ( "fmt" "log" "time" ) func main() { const USPacificTimeZone = "US/Pacific" location, err := time.LoadLocation(USPacificTimeZone) if err != nil { log.Fatalf("Couldn't load timezone: %v", err) } location2, err := time.LoadLocation(USPacificTimeZone) if err != nil { log.Fatalf("Couldn't load timezone: %v", err) } now := time.Now() fmt.Printf("Times using same location object: %v\n", now.In(location).Equal(now.In(location))) // 输出: true fmt.Printf("Times using different location objects: %v\n", now.In(location).Equal(now.In(location2))) // 输出: true }
内容的提问来源于stack exchange,提问作者Peter V. Mørch
相关产品推荐
相关产品推荐

