I got a bug in Go when using an interface{} as function parameter type, when given a non-pointer type, and using json.Unmarshal with it.
Because a piece of code is worth a thousand words, here is an example:
package main import ( "encoding/json" "fmt" ) func test(i interface{}) { j := []byte(`{ "foo": "bar" }`) fmt.Printf("%T\n", i) fmt.Printf("%T\n", &i) json.Unmarshal(j, &i) fmt.Printf("%T\n", i) } type Test struct { Foo string } func main() { test(Test{}) } Which outputs:
main.Test *interface {} map[string]interface {} json.Unmarshal turns my struct to a map[string]interface{} oO...
Little readings later explains some of it, interface{} is a type in itself, not some sort of typeless container, which explains the *interface{}, and the fact that json.Unmarshal could not get the initial type, and returned a map[string]interface{}..
From Unmarshal docs:
To unmarshal JSON into an interface value, Unmarshal stores one of these in the interface value: [...]
And if I pass a pointer to the test function like so, it works:
func test(i interface{}) { j := []byte(`{ "foo": "bar" }`) fmt.Printf("%T\n", i) fmt.Printf("%T\n", &i) json.Unmarshal(j, i) fmt.Printf("%T\n", i) fmt.Println(i) } func main() { test(&Test{}) } Which outputs:
*main.Test *interface {} *main.Test &{bar} Cool, the data is unmarshalled and all, now in this second snippet I removed the & when calling Unmarshal. Because I have a *Test in i, no use for it.
So in all logic, if I put back the & to i when calling Unmarshal it should mess up with i's type again. But no.
If I run:
func test(i interface{}) { j := []byte(`{ "foo": "bar" }`) fmt.Printf("%T\n", i) fmt.Printf("%T\n", &i) json.Unmarshal(j, &i) fmt.Printf("%T\n", i) fmt.Println(i) } func main() { test(&Test{}) } Well it still works:
*main.Test *interface {} *main.Test &{bar} And now I'm out of google search queries.