我尝试将我的Go代码从1.8更新到1.9。但是,我遇到了一些问题:
package simple_struct
import (
"time"
"encoding/json"
"github.com/stretchr/testify/assert"
"testing"
)
type SimpleStruct struct {
CreateTime time.Time
Other string
}
func NewSimpleStruct() *SimpleStruct {
return &SimpleStruct{
CreateTime: time.Now(),
}
}
func Test(t *testing.T) {
s1 := NewSimpleStruct()
data, err := json.Marshal(s1)
assert.Nil(t, err)
s2 := &SimpleStruct{}
err = json.Unmarshal(data, s2)
assert.Nil(t, err)
assert.Equal(t, s2, s1)
// this is not equal
// output:
/*
Diff:
--- Expected
+++ Actual
@@ -1,3 +1,3 @@
(*simple_struct.SimpleStruct)({
- CreateTime: (time.Time) 2017-12-01 14:54:53.948875421 +0800 CST,
+ CreateTime: (time.Time) 2017-12-01 14:54:53.948875421 +0800 CST m=+0.001827244,
*/
}
它适用于Golang 1.8,但不适用于Golang 1.9。
我知道Golang 1.9有更新time.Time
,但我不明白这一点。
答案 0 :(得分:2)
可能与编组时擦除单调时间有关。请参阅包文档
答案 1 :(得分:2)
import "time"
请注意,Go ==运算符不仅会比较时刻,还会比较 还有位置和单调时钟读数。
func (t Time) Equal(u Time) bool
Equal报告t和u是否代表同一时刻。二 即使它们位于不同的位置,时间也可以相等。对于 例如,6:00 + 0200 CEST和4:00 UTC是相等的。请参阅文档 关于使用==与时间值的陷阱的时间类型;最 代码应该使用Equal。
// A Time represents an instant in time with nanosecond precision.
//
// Time instants can be compared using the Before, After, and Equal methods.
//
// Note that the Go == operator compares not just the time instant but also the
// Location and the monotonic clock reading. 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, and that the monotonic clock reading
// has been stripped by setting t = t.Round(0). In general, prefer t.Equal(u)
// to t == u, since t.Equal uses the most accurate comparison available and
// correctly handles the case when only one of its arguments has a monotonic
// clock reading.
//
type Time struct {
// wall and ext encode the wall time seconds, wall time nanoseconds,
// and optional monotonic clock reading in nanoseconds.
//
// From high to low bit position, wall encodes a 1-bit flag (hasMonotonic),
// a 33-bit seconds field, and a 30-bit wall time nanoseconds field.
// The nanoseconds field is in the range [0, 999999999].
// If the hasMonotonic bit is 0, then the 33-bit field must be zero
// and the full signed 64-bit wall seconds since Jan 1 year 1 is stored in ext.
// If the hasMonotonic bit is 1, then the 33-bit field holds a 33-bit
// unsigned wall seconds since Jan 1 year 1885, and ext holds a
// signed 64-bit monotonic clock reading, nanoseconds since process start.
wall uint64
ext int64
// loc specifies the Location that should be used to
// determine the minute, hour, month, day, and year
// that correspond to this Time.
// The nil location means UTC.
// All UTC times are represented with loc==nil, never loc==&utcLoc.
loc *Location
}
长期以来一直是这样,不仅仅是现在(go1.9 +),通过比较实现(opaque time.Time
)和Go equal运算符来比较Go struct
是错误的。 (==
)。例如,早在go1.4,
请注意,Go
==
运算符不仅会比较时刻,还会比较 也是位置。因此,时间值不应用作地图或 数据库密钥没有先保证相同的位置 已经为所有值设置了,这可以通过使用来实现 UTC或本地方法。
go1.9只是向不透明的time.Time
struct
添加了一个额外的元素,一个单调的值。
始终使用time.Equal
方法断言time.Time
相等。
例如,
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now() // wall, location, & monotonic
fmt.Println("Now: ", now)
clock := now.Round(0) // wall & location
fmt.Println("Clock: ", clock)
utc := now.UTC() // wall & location UTC
fmt.Println("UTC: ", utc)
fmt.Println("now.Equal(clock)", now.Equal(clock)) // true
fmt.Println("now == clock ", now == clock) // false
fmt.Println("now.Equal(utc) ", now.Equal(utc)) // true
fmt.Println("now == utc ", now == utc) // false
fmt.Println("clock.Equal(utc)", clock.Equal(utc)) // true
fmt.Println("clock == utc ", clock == utc) // false
}
游乐场:https://play.golang.org/p/VbFV2AcYw-
输出:
Now: 2017-12-01 14:54:15.168706745 -0500 EST m=+0.000899521
Clock: 2017-12-01 14:54:15.168706745 -0500 EST
UTC: 2017-12-01 19:54:15.168706745 +0000 UTC
now.Equal(clock) true
now == clock false
now.Equal(utc) true
now == utc false
clock.Equal(utc) true
clock == utc false