I found an unclear and a bit strange thing in comparison of unmarshaled values of JSON when you using interface{} and it's type detection. package main
import (
"fmt"
"os"
"encoding/json"
"reflect"
)
type Message struct {
Code int `json:"code"`
}
func main() {
var jsons []byte = []byte(`{ "code":200 }`)
var t = make(map[string]interface{})
e:= json.Unmarshal(jsons, &t)
if e != nil {
fmt.Printf("Unmarshal error: %v", e)
os.Exit(1)
}
var c float64 = 200
fmt.Printf("Comparison with manually defined float64: %t
",c == 200) /// comparison with float64 is ok
fmt.Printf("Type of 'code' value: %s
", reflect.TypeOf(t["code"])) // here is a float64 type
fmt.Printf("Comparison without type assertion: %t
", t["code"] == 200) // returning false
fmt.Printf("Comparison with type assertion: %t
", t["code"].(float64) == 200) // returning true
fmt.Printf("
%", t["code"])
fmt.Printf("
%", t["code"].(float64))
}
Output:
Comparison with manually defined float64: true
Type of 'code' value: float64
Comparison without type assertion: false
Comparison with type assertion: true
%!(NOVERB)%!(EXTRA float64=200)
%!(NOVERB)%!(EXTRA float64=200)
As you can see, that 2 variables look same, has same type and value, but the result of a comparison is different.
Can somebody help me to understand why?
Here is a playground - https://play.golang.org/p/KaB_UwDK2N
The value 200
is an untyped constant. The spec says this about untyped constants:
An untyped constant has a default type which is the type to which the constant is implicitly converted in contexts where a typed value is required, for instance, in a short variable declaration such as i := 0 where there is no explicit type. The default type of an untyped constant is bool, rune, int, float64, complex128 or string respectively, depending on whether it is a boolean, rune, integer, floating-point, complex, or string constant.
The expression t["code"] == 200
evaluates to false because the untyped 200
is implicitly converted to the default int
for the comparison with interface{}
. The float64
in the interface{}
is not equal to the int
200.
The other comparisons return true because implicit type conversions to the default type are not needed.
The expression t["code"] == 200.0
evaluates to true because 200.0
is a float64
constant.
The comparison results are unrelated to JSON decoding. See https://play.golang.org/p/4BXMI0SnoL.