无法解组简单日期

I am starting A tour of Go, but I am experimenting on the way.

I wrote a piece of code:

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    actualTime := time.Now()
    fmt.Println(actualTime)
    var marshalledtime []byte
    marshalledtime,_ := actualTime.MarshalJSON()
    fmt.Println(marshalledtime)
    actualTime := (*time.Time).UnmarshalJSON(marshalledtime)
    fmt.Println(actualTime)
}

I just wanted to marshal a simple date, and then unmarshal it to just see the process.

But I am completely overhelmed with problems. Up to today GO seemed to be so simple and logical, but now... I don't know, I am stuck.

./compile219.go:27:13: cannot use time.(*Time).UnmarshalJSON(marshalledtime) (type error) as type time.Time in assignment
./compile219.go:27:42: not enough arguments in call to method expression time.(*Time).UnmarshalJSON
 have ([]byte)
want (*time.Time, []byte)

Why does the last error mean? The documentation clearly says that UnmarshalJson takes only one argument, byte[].

What is with the type conversion error?

The documentation clearly says that UnmarshalJson takes only one argument, byte[]

UnmarshalJson is the method in case you want to redefine the behavior of Unmarshal on a struct. That's not the case here. You don't have to use it unless you want to customize Unmarshal. Then UnmarshalJson will be called under the hood when you will make a call to Unmarshal

By the way, if you see the signature of UnmarshalJson you will see that it does return only an error.

Here is a fix using json.Unmarshal

package main

import (
    "fmt"
    "encoding/json"
    "time"
)

func main() {
    actualTime := time.Now()
    fmt.Println(actualTime)
    var marshalledtime []byte
    marshalledtime,_ = actualTime.MarshalJSON()
    fmt.Println(marshalledtime)
    json.Unmarshal(marshalledtime, &actualTime)
    fmt.Println(actualTime)
}

actualTime.MarshalJSON() is a method call, it calls the Time.MarshalJSON() method. It returns you the bytes of the JSON representation of the time. Since the bytes printed are not well readable, you should print the byte slice as a string, e.g.:

fmt.Println("Raw:", marshalledtime)
fmt.Println("String:", string(marshalledtime))

Which outputs:

Raw: [34 50 48 48 57 45 49 49 45 49 48 84 50 51 58 48 48 58 48 48 90 34]
String: "2009-11-10T23:00:00Z"

UnmarshalJSON() is also a method of time.Time, so you need a time.Time value to call it "on", for example:

var time2 time.Time
time2.UnmarshalJSON(marshalledtime)

(To be precise, UnmarshalJSON() requires a pointer of type *time.Time because it has to modify the time.Time value, but the Go compiler will rewrite time2.UnmarshalJSON() to take time2's address: (&time2).UnmarshalJSON()).

MarshalJSON() and UnmarshalJSON() also return an error which you should always check, for example:

var marshalledtime []byte
var err error
marshalledtime, err = actualTime.MarshalJSON()
if err != nil {
    panic(err)
}

And:

var time2 time.Time
err = time2.UnmarshalJSON(marshalledtime)
if err != nil {
    panic(err)
}

Try the fixed code on the Go Playground.

Also note that it's rare that someone calls Time.MarshalJSON() and Time.UnmarshalJSON() "by hand". They are to implement the json.Marshaler and json.Unmarshaler interfaces, so when you marshal / unmarshal time values, the encoding/json package will call these methods to do the JSON conversion.

This is how the same can be achieved using the encoding/json package (try it on the Go Playground):

Marshaling:

var marshalledtime []byte
var err error
marshalledtime, err = json.Marshal(actualTime)
if err != nil {
    panic(err)
}

Unmarshaling:

var time2 time.Time
err = json.Unmarshal(marshalledtime, &time2)
if err != nil {
    panic(err)
}

Although it's not simpler or shorter in this case, the encoding/json package is capable of marshaling / unmarshaling arbitrary complex data structures, not just simple time values.