为什么与 == 相比,具有相同日期和时间的 2 个时间结构 return 为 false?
Why do 2 time structs with the same date and time return false when compared with ==?
我有一个 time.Time
使用 time.Date()
创建的。然后我计算 1970/1/1 00:00:00.000000000
和那个时间之间的纳秒数。
然后我使用 time.Unix()
.
将纳秒转换回 time.Time
但是,如果我使用 ==
将重构时间与原始时间进行比较,它 return 是错误的。如果我减去这 2 次,则结果持续时间为 0。如果我使用 time.Equal()
比较这 2 次,则 return 为真。
如果我使用 time.Date()
创建另一个时间,其值与第一次相同,则使用 ==
比较这个新时间和原始时间结果为真。
这是演示这一点的代码 (Golang Playground):
package main
import (
"fmt"
"time"
)
func main() {
t1 := time.Date(2016, 4, 14, 1, 30, 30, 222000000, time.UTC)
base := time.Date(1970, 1, 1, 0, 0, 0, 0, t1.Location())
nsFrom1970 :=t1.Sub(base).Nanoseconds() // Calculate the number of nanoseconds from 1970/1/1 to t1
t2 := time.Unix(0, nsFrom1970)
fmt.Println(t1)
fmt.Println(t2)
fmt.Println(t1.Sub(t2)) // 0
fmt.Println(t1 == t2) //false
fmt.Println(t1.Equal(t2)) //true
t3 := time.Date(2100, 2, 1, 21, 21, 21, 222000000, time.UTC)
fmt.Println(t1 == t3) //true
}
为什么重构的时间和原来的时间相比return是假的?
time.Time
is a struct
. When you try to compare them with ==
, quoting from the Spec: Comparison operator:
Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.
因此 t1 == t2
将比较 2 Time
结构值的所有字段。 Time
结构不仅包含自基准时间以来的秒和纳秒,它还包含作为指针的位置:*Location
,因此 ==
也会比较位置字段。比较指针:
Pointer values are comparable. Two pointer values are equal if they point to the same variable or if both have value nil
. Pointers to distinct zero-size variables may or may not be equal.
这就是为什么将时间与 ==
进行比较会得到 false
结果:2 个位置可能表示相同的位置,即使它们的地址不同,这就是您的情况。
证明这一点:
fmt.Println("Locations:", t1.Location(), t2.Location())
fmt.Printf("Location pointers: %p %p\n", t1.Location(), t2.Location())
fmt.Println("Locations equal:", t1.Location() == t2.Location())
输出:
Locations: UTC UTC
Location pointers: 0x1e2100 0x1e6de0
Locations equal: false
这记录在 time.Time
:
Note that the Go == operator compares not just the time instant but also the Location. Therefore, Time values should not be used as map or database keys without first guaranteeing that the identical Location has been set for all values, which can be achieved through use of the UTC or Local method.
如果 t1
和 t2
也包含相同的 *Location
指针,即使与 ==
运算符相比,它们也是相等的。这可以通过调用 Time.UTC()
or Time.Local()
method on them which returns a time.Time
value where the same location pointer (*Location
) is used. Or by using the Time.In()
方法来确保,该方法将 设置 指定的位置指针(在正确转换之后),例如:
t2 = t2.In(t1.Location())
fmt.Println("Locations:", t1.Location(), t2.Location())
fmt.Printf("Location pointers: %p %p\n", t1.Location(), t2.Location())
fmt.Println("Locations equal:", t1.Location() == t2.Location())
fmt.Println(t1 == t2) // Now true
fmt.Println(t1.Equal(t2)) // Still true
输出:
Locations: UTC UTC
Location pointers: 0x1e2100 0x1e2100
Locations equal: true
true
true
在 Go Playground 上试试。
我有一个 time.Time
使用 time.Date()
创建的。然后我计算 1970/1/1 00:00:00.000000000
和那个时间之间的纳秒数。
然后我使用 time.Unix()
.
time.Time
但是,如果我使用 ==
将重构时间与原始时间进行比较,它 return 是错误的。如果我减去这 2 次,则结果持续时间为 0。如果我使用 time.Equal()
比较这 2 次,则 return 为真。
如果我使用 time.Date()
创建另一个时间,其值与第一次相同,则使用 ==
比较这个新时间和原始时间结果为真。
这是演示这一点的代码 (Golang Playground):
package main
import (
"fmt"
"time"
)
func main() {
t1 := time.Date(2016, 4, 14, 1, 30, 30, 222000000, time.UTC)
base := time.Date(1970, 1, 1, 0, 0, 0, 0, t1.Location())
nsFrom1970 :=t1.Sub(base).Nanoseconds() // Calculate the number of nanoseconds from 1970/1/1 to t1
t2 := time.Unix(0, nsFrom1970)
fmt.Println(t1)
fmt.Println(t2)
fmt.Println(t1.Sub(t2)) // 0
fmt.Println(t1 == t2) //false
fmt.Println(t1.Equal(t2)) //true
t3 := time.Date(2100, 2, 1, 21, 21, 21, 222000000, time.UTC)
fmt.Println(t1 == t3) //true
}
为什么重构的时间和原来的时间相比return是假的?
time.Time
is a struct
. When you try to compare them with ==
, quoting from the Spec: Comparison operator:
Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.
因此 t1 == t2
将比较 2 Time
结构值的所有字段。 Time
结构不仅包含自基准时间以来的秒和纳秒,它还包含作为指针的位置:*Location
,因此 ==
也会比较位置字段。比较指针:
Pointer values are comparable. Two pointer values are equal if they point to the same variable or if both have value
nil
. Pointers to distinct zero-size variables may or may not be equal.
这就是为什么将时间与 ==
进行比较会得到 false
结果:2 个位置可能表示相同的位置,即使它们的地址不同,这就是您的情况。
证明这一点:
fmt.Println("Locations:", t1.Location(), t2.Location())
fmt.Printf("Location pointers: %p %p\n", t1.Location(), t2.Location())
fmt.Println("Locations equal:", t1.Location() == t2.Location())
输出:
Locations: UTC UTC
Location pointers: 0x1e2100 0x1e6de0
Locations equal: false
这记录在 time.Time
:
Note that the Go == operator compares not just the time instant but also the Location. Therefore, Time values should not be used as map or database keys without first guaranteeing that the identical Location has been set for all values, which can be achieved through use of the UTC or Local method.
如果 t1
和 t2
也包含相同的 *Location
指针,即使与 ==
运算符相比,它们也是相等的。这可以通过调用 Time.UTC()
or Time.Local()
method on them which returns a time.Time
value where the same location pointer (*Location
) is used. Or by using the Time.In()
方法来确保,该方法将 设置 指定的位置指针(在正确转换之后),例如:
t2 = t2.In(t1.Location())
fmt.Println("Locations:", t1.Location(), t2.Location())
fmt.Printf("Location pointers: %p %p\n", t1.Location(), t2.Location())
fmt.Println("Locations equal:", t1.Location() == t2.Location())
fmt.Println(t1 == t2) // Now true
fmt.Println(t1.Equal(t2)) // Still true
输出:
Locations: UTC UTC
Location pointers: 0x1e2100 0x1e2100
Locations equal: true
true
true
在 Go Playground 上试试。