Why time.Time not equal after bson.Marshal and bson.Unmarshal? - go

Why does it output false? I was expecting true...
package main
import (
"fmt"
"time"
"gopkg.in/mgo.v2/bson"
)
type S struct {
T time.Time
}
func main() {
t := S{time.Now()}
bytes, _ := bson.Marshal(t)
var dt S
bson.Unmarshal(bytes, &dt)
fmt.Println(dt.T.Equal(t.T))
}
go run the above will output false, why Marshal/Unmarshal doesn't preserve the original value?

Bson stores time with lower precision than a time.Time, the value returned from Bson may not equal the value you stored.
You need to use bson.Now():
package main
import (
"fmt"
"gopkg.in/mgo.v2/bson"
"time"
)
type S struct {
T time.Time
}
func main() {
t := S{bson.Now()}
bytes, _ := bson.Marshal(t)
var dt S
bson.Unmarshal(bytes, &dt)
fmt.Println(dt.T)
fmt.Println(t.T)
fmt.Println(dt.T.Equal(t.T))
}
Output:
$> go run main.go
2018-09-08 10:48:42.45 +0300 MSK
2018-09-08 10:48:42.45 +0300 MSK
true

Related

Golang reflection slice shows up as struct

package main
import (
"fmt"
"encoding/json"
"reflect"
)
func someFunc( data interface{}, out interface{} ) {
v := reflect.ValueOf(out).Elem();
fmt.Printf("Incoming type: %s\n",reflect.ValueOf(v).Kind())
v.SetCap(reflect.ValueOf(data).Len())
}
func main() {
expected := []int{1,2,3}
jsonRaw, _ := json.Marshal(expected)
var tmpData interface{}
json.Unmarshal(jsonRaw, &tmpData)
fmt.Printf("%s\n",string(jsonRaw))
fmt.Printf("%#v\n",tmpData)
result := []int{}
var tmp interface{}
tmp = result
fmt.Printf("Outcoming type: %s\n",reflect.TypeOf(&tmp))
someFunc(tmpData,&tmp)
}
I would like to operate on v parameter inside someFunc as if it were
a slice, i.e. "Incoming type"-debug message should output slice.
However, it outputs struct, as is shown here.
The ultimate goal is that I use reflection to analyze the data-parameter's contents and recover everything into out, but for now I would like to
know how to make sure the correct type of v is detected,
so that I can use it as a slice.
EDIT: It appears to be impossible (as of 2013 at least): https://groups.google.com/forum/#!topic/golang-nuts/bldM9tIL-JM
to set the size of a slice for stuff discovered at runtime.
One of the authors says something to the effect that "you have to be able
to sort the elements, i.e. implement Less()" for the values...
EDIT: In any case, I did try to use MakeSlice in this Playgound link,
and it says reflect.MakeSlice of non-slice type
EDIT: I apologize and thank you all for your comments.
What I ended up doing is the following (after an illuminating read of the source code of MakeSlice):
package main
import (
"fmt"
"encoding/json"
"reflect"
)
func someFunc( data interface{}, out interface{} ) {
v := reflect.ValueOf(out).Elem();
fmt.Printf("Incoming type: %s\n",v.Kind())
//v.SetCap(reflect.ValueOf(data).Len()) <-- doesn't work
n := reflect.ValueOf(data).Len()
s := reflect.MakeSlice(reflect.TypeOf(data),n,n)
fmt.Printf("Len= %d\n",s.Len())
}
func main() {
expected := []int{1,2,3}
jsonRaw, _ := json.Marshal(expected)
var tmpData interface{}
json.Unmarshal(jsonRaw, &tmpData)
fmt.Printf("%s\n",string(jsonRaw))
fmt.Printf("%#v\n",tmpData)
result := []int{}
someFunc(tmpData,&result)
}
What I ended up doing is the following (after an illuminating read of the source code of MakeSlice):
package main
import (
"fmt"
"encoding/json"
"reflect"
)
func someFunc( data interface{}, out interface{} ) {
v := reflect.ValueOf(out).Elem();
fmt.Printf("Incoming type: %s\n",v.Kind())
//v.SetCap(reflect.ValueOf(data).Len()) <-- doesn't work
n := reflect.ValueOf(data).Len()
s := reflect.MakeSlice(reflect.TypeOf(data),n,n)
fmt.Printf("Len= %d\n",s.Len())
}
func main() {
expected := []int{1,2,3}
jsonRaw, _ := json.Marshal(expected)
var tmpData interface{}
json.Unmarshal(jsonRaw, &tmpData)
fmt.Printf("%s\n",string(jsonRaw))
fmt.Printf("%#v\n",tmpData)
result := []int{}
someFunc(tmpData,&result)
}
It appears that there are convenience functions such as SliceOf, too.
the bottomline is that the first argument of MakeSlice is not the type
of the arguments that the slice holds, but the slice-type, e.g. []int rather than int.

Printing value along with it's data type

package main
import "fmt"
func main() {
anInt := 1234
fmt.Printf("Data Type:", "%T\n", anInt, "Value is:", anInt)
}
Ouput:
Data Type:%!(EXTRA string=%T
, int=1234, string=Value is:, int=1234)
But Expected Output:
Data Type: int, Value is: 1234
I have tried using import reflect still not the expected result
Data Type:%!(EXTRA *reflect.rtype=int, string=Value is:, int=1234)
Package fmt
import "fmt"
func Printf
func Printf(format string, a ...interface{}) (n int, err error)
Printf formats according to a format specifier and writes to standard
output. It returns the number of bytes written and any write error
encountered.
It's a single format string. For example,
package main
import "fmt"
func main() {
anInt := 1234
fmt.Printf("Data Type: %T\nValue is: %v\n", anInt, anInt)
// or, concise version
fmt.Printf("Data Type: %[1]T\nValue is: %[1]v\n", anInt)
}
Output:
Data Type: int
Value is: 1234
Data Type: int
Value is: 1234

How can I parse []int JSON data in Go?

I try parse JSON data include integer array. But, I can't get integer array.
package main
import (
"encoding/json"
"fmt"
)
type Anything struct {
A []int `json:"a"`
}
func main() {
s := "{a:[1,2,3]}"
var a Anything
json.Unmarshal([]byte(s), &a)
fmt.Println(a.A)
}
I got empty array.
[]
How can I get [1, 2, 3]?
{a:[1,2,3]} is not valid JSON. Object keys must be double-quoted. Changing it like this works as expected:
s := "{\"a\":[1,2,3]}"
https://play.golang.org/p/qExZAeiRJy
You have an invalid JSON. You should replace it, for example like this: s := [{"a":[1,2,3]}] or maybe like this s := "[{\"a\":[1,2,3]}]".
You can edit your code to something like this:
package main
import (
"encoding/json"
"fmt"
)
type Anything struct {
A []int `json:"a"`
}
func main() {
// note here: `[{"a":[1,2,3]}]`
// or: s := "[{\"a\":[1,2,3]}]"
s := `[{"a":[1,2,3]}]`
var a []Anything
json.Unmarshal([]byte(s), &a)
fmt.Println(a)
}
Output:
[{[1 2 3]}]
You can run it on https://play.golang.org/p/H4GupGFpfP

Generating Random Timestamps in Go

I'd like to generate a random timestamp within the last relative 3 years and have it be printed out with this format: %d/%b/%Y:%H:%M:%S %z
Here is what I have right now:
package main
import (
"strconv"
"time"
"math/rand"
"fmt"
)
func randomTimestamp() time.Time {
randomTime := rand.Int63n(time.Now().Unix() - 94608000) + 94608000
randomNow, err := time.Parse("10/Oct/2000:13:55:36 -0700", strconv.FormatInt(randomTime, 10))
if err != nil {
panic(err)
}
return randomNow
}
func main() {
fmt.Println(randomTimestamp().String())
}
This always throws: panic: parsing time "...": month out of range. How can I generate a random timestamp for a given range, then convert it to the string format I want with the standard library?
Don't use time.Parse. You have a Unix time, not a time string. Use the Unix() method instead. https://golang.org/pkg/time/#Unix. You can also choose a minimum time value, say 1/1/1900 and add a random Duration of seconds to the time using the Add method on Time and passing a Duration you made with the Ticks() method. https://golang.org/pkg/time/#Duration
Here's a Go Playground link. Just remember that the Go Playground doesn't support actual randomness. https://play.golang.org/p/qYTpnbml_N
package main
import (
"time"
"math/rand"
"fmt"
)
func randomTimestamp() time.Time {
randomTime := rand.Int63n(time.Now().Unix() - 94608000) + 94608000
randomNow := time.Unix(randomTime, 0)
return randomNow
}
func main() {
fmt.Println(randomTimestamp().String())
}

How to find the type of an object in Go?

How do I find the type of an object in Go? In Python, I just use typeof to fetch the type of object. Similarly in Go, is there a way to implement the same ?
Here is the container from which I am iterating:
for e := dlist.Front(); e != nil; e = e.Next() {
lines := e.Value
fmt.Printf(reflect.TypeOf(lines))
}
I am not able to get the type of the object lines in this case which is an array of strings.
The Go reflection package has methods for inspecting the type of variables.
The following snippet will print out the reflection type of a string, integer and float.
package main
import (
"fmt"
"reflect"
)
func main() {
tst := "string"
tst2 := 10
tst3 := 1.2
fmt.Println(reflect.TypeOf(tst))
fmt.Println(reflect.TypeOf(tst2))
fmt.Println(reflect.TypeOf(tst3))
}
Output:
string
int
float64
see: http://play.golang.org/p/XQMcUVsOja to view it in action.
More documentation here: http://golang.org/pkg/reflect/#Type
I found 3 ways to return a variable's type at runtime:
Using string formatting
func typeof(v interface{}) string {
return fmt.Sprintf("%T", v)
}
Using reflect package
func typeof(v interface{}) string {
return reflect.TypeOf(v).String()
}
Using type switch
func typeof(v interface{}) string {
switch v.(type) {
case int:
return "int"
case float64:
return "float64"
//... etc
default:
return "unknown"
}
}
Every method has a different best use case:
string formatting - short and low footprint (not necessary to import reflect package)
reflect package - when need more details about the type we have access to the full reflection capabilities
type switch - allows grouping types, for example recognize all int32, int64, uint32, uint64 types as "int"
Use the reflect package:
Package reflect implements run-time reflection, allowing a program to
manipulate objects with arbitrary types. The typical use is to take a
value with static type interface{} and extract its dynamic type
information by calling TypeOf, which returns a Type.
package main
import (
"fmt"
"reflect"
)
func main() {
b := true
s := ""
n := 1
f := 1.0
a := []string{"foo", "bar", "baz"}
fmt.Println(reflect.TypeOf(b))
fmt.Println(reflect.TypeOf(s))
fmt.Println(reflect.TypeOf(n))
fmt.Println(reflect.TypeOf(f))
fmt.Println(reflect.TypeOf(a))
}
Produces:
bool
string
int
float64
[]string
Playground
Example using ValueOf(i interface{}).Kind():
package main
import (
"fmt"
"reflect"
)
func main() {
b := true
s := ""
n := 1
f := 1.0
a := []string{"foo", "bar", "baz"}
fmt.Println(reflect.ValueOf(b).Kind())
fmt.Println(reflect.ValueOf(s).Kind())
fmt.Println(reflect.ValueOf(n).Kind())
fmt.Println(reflect.ValueOf(f).Kind())
fmt.Println(reflect.ValueOf(a).Index(0).Kind()) // For slices and strings
}
Produces:
bool
string
int
float64
string
Playground
To get a string representation:
From http://golang.org/pkg/fmt/
%T a Go-syntax representation of the type of the value
package main
import "fmt"
func main(){
types := []interface{} {"a",6,6.0,true}
for _,v := range types{
fmt.Printf("%T\n",v)
}
}
Outputs:
string
int
float64
bool
I would stay away from the reflect. package. Instead use %T
package main
import (
"fmt"
)
func main() {
b := true
s := ""
n := 1
f := 1.0
a := []string{"foo", "bar", "baz"}
fmt.Printf("%T\n", b)
fmt.Printf("%T\n", s)
fmt.Printf("%T\n", n)
fmt.Printf("%T\n", f)
fmt.Printf("%T\n", a)
}
Best way is using reflection concept in Google.
reflect.TypeOf gives type along with the package name
reflect.TypeOf().Kind() gives underlining type
To be short, please use fmt.Printf("%T", var1) or its other variants in the fmt package.
If we have this variables:
var counter int = 5
var message string = "Hello"
var factor float32 = 4.2
var enabled bool = false
1: fmt.Printf %T format : to use this feature you should import "fmt"
fmt.Printf("%T \n",factor ) // factor type: float32
2: reflect.TypeOf function : to use this feature you should import "reflect"
fmt.Println(reflect.TypeOf(enabled)) // enabled type: bool
3: reflect.ValueOf(X).Kind() : to use this feature you should import "reflect"
fmt.Println(reflect.ValueOf(counter).Kind()) // counter type: int
You can check the type of any variable/instance at runtime either using the "reflect" packages TypeOf function or by using fmt.Printf():
package main
import (
"fmt"
"reflect"
)
func main() {
value1 := "Have a Good Day"
value2 := 50
value3 := 50.78
fmt.Println(reflect.TypeOf(value1 ))
fmt.Println(reflect.TypeOf(value2))
fmt.Println(reflect.TypeOf(value3))
fmt.Printf("%T",value1)
fmt.Printf("%T",value2)
fmt.Printf("%T",value3)
}
To get the type of fields in struct
package main
import (
"fmt"
"reflect"
)
type testObject struct {
Name string
Age int
Height float64
}
func main() {
tstObj := testObject{Name: "yog prakash", Age: 24, Height: 5.6}
val := reflect.ValueOf(&tstObj).Elem()
typeOfTstObj := val.Type()
for i := 0; i < val.NumField(); i++ {
fieldType := val.Field(i)
fmt.Printf("object field %d key=%s value=%v type=%s \n",
i, typeOfTstObj.Field(i).Name, fieldType.Interface(),
fieldType.Type())
}
}
Output
object field 0 key=Name value=yog prakash type=string
object field 1 key=Age value=24 type=int
object field 2 key=Height value=5.6 type=float64
See in IDE https://play.golang.org/p/bwIpYnBQiE
You can use: interface{}..(type) as in this playground
package main
import "fmt"
func main(){
types := []interface{} {"a",6,6.0,true}
for _,v := range types{
fmt.Printf("%T\n",v)
switch v.(type) {
case int:
fmt.Printf("Twice %v is %v\n", v, v.(int) * 2)
case string:
fmt.Printf("%q is %v bytes long\n", v, len(v.(string)))
default:
fmt.Printf("I don't know about type %T!\n", v)
}
}
}
For arrays and slices use Type.Elem():
a := []string{"foo", "bar", "baz"}
fmt.Println(reflect.TypeOf(a).Elem())
I have organized the following.
fmt %T : a Go-syntax representation of the type of the value
reflect.TypeOf.String()
reflect.TypeOf.Kind()
type assertions
Example
package _test
import (
"fmt"
"reflect"
"testing"
)
func TestType(t *testing.T) {
type Person struct {
name string
}
var i interface{}
i = &Person{"Carson"}
for idx, d := range []struct {
actual interface{}
expected interface{}
}{
{fmt.Sprintf("%T", "Hello") == "string", true},
{reflect.TypeOf("string").String() == "string", true},
{reflect.TypeOf("string").Kind() == reflect.String, true},
{reflect.TypeOf(10).String() == "int", true},
{reflect.TypeOf(10).Kind() == reflect.Int, true},
{fmt.Sprintf("%T", 1.2) == "float64", true},
{reflect.TypeOf(1.2).String() == "float64", true},
{reflect.TypeOf(1.2).Kind() == reflect.Float64, true},
{reflect.TypeOf([]byte{3}).String() == "[]uint8", true},
{reflect.TypeOf([]byte{3}).Kind() == reflect.Slice, true},
{reflect.TypeOf([]int8{3}).String() == "[]int8", true},
{reflect.TypeOf([]int8{3}).Kind() == reflect.Slice, true},
{reflect.TypeOf(Person{"carson"}).Kind() == reflect.Struct, true},
{reflect.TypeOf(&Person{"carson"}).Kind() == reflect.Ptr, true},
{fmt.Sprintf("%v", i.(*Person)) == "&{Carson}", true},
{fmt.Sprintf("%+v", i.(*Person)) == "&{name:Carson}", true},
} {
if d.actual != d.expected {
t.Fatalf("%d | %s", idx, d.actual)
}
}
}
go playground
In case if you want to detect the type within if expression:
if str, ok := myvar.(string); ok {
print("It's a string")
}
Or without type assertion (may produce errors):
if reflect.TypeOf(myvar).String() == "string" {
print("It's a string")
}
you can use reflect.TypeOf.
basic type(e.g.: int, string): it will return its name (e.g.: int, string)
struct: it will return something in the format <package name>.<struct name> (e.g.: main.test)
reflect package comes to rescue:
reflect.TypeOf(obj).String()
Check this demo

Resources