tendermint / go-amino

Protobuf3 with Interface support - Designed for blockchains (deterministic, upgradeable, fast, and compact)
Other
259 stars 78 forks source link

Using time.Time pointer with nil value in Structs #249

Closed ironman0x7b2 closed 5 years ago

ironman0x7b2 commented 5 years ago
package main

import (
    "fmt"
    "time"

    "github.com/tendermint/go-amino"
)

type Test struct {
    T *time.Time
}

func main() {
    var t1 = Test{}
    var t2 Test

    t1Bytes := amino.MustMarshalBinaryLengthPrefixed(t1)
    amino.MustUnmarshalBinaryLengthPrefixed(t1Bytes, &t2)

    fmt.Println(t1, t1Bytes, t2)
}

In the above code, why am I getting Unix start time when I do unmarshal? How can I get nil for the field T when I do unmarshal?

liamsi commented 5 years ago

In the above code, why am I getting Unix start time when I do unmarshal?

In amino, as in protobuf with which we want to be compatible, there is no difference in encoding default values and empty/missing values. The default value for time is the unix start time.

Time is a bit tricky though: In protobuf the equivalent struct would actually be decoded as you expected (nil). See for instance this test: https://github.com/tendermint/go-amino/blob/dc14acf9ef15f85828bfbc561ed9dd9d2a284885/tests/proto3/proto3_compat_test.go#L166-L185

The difference in amino is that we directly deal with encoding/decoding the time.Time struct. So what you get at the end (epoch time) is what what protobuf would give you if you go from google.protobuf.Timestamp to time.Time (by using https://godoc.org/github.com/golang/protobuf/ptypes#Timestamp). Does that make sense to you? Do you think amino should behave differently here?

How can I get nil for the field T when I do unmarshal?

Currently you can't AFAIR.

ironman0x7b2 commented 5 years ago

@Liamsi Thank you for your clarification