Marshal和Unmarshal一个时间。时间,得到不同的价值观

时间:2017-12-01 07:07:24

标签: json go

我尝试将我的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,但我不明白这一点。

2 个答案:

答案 0 :(得分:2)

可能与编组时擦除单调时间有关。请参阅包文档

答案 1 :(得分:2)

  

Package time

     

import "time"

     

请注意,Go ==运算符不仅会比较时刻,还会比较   还有位置和单调时钟读数。

     

func (Time) Equal

     

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