There are 2 kinds of variables that I have. Check for the Go playground, and I don't understand why this is happening. The problem: what I get from the Models
it should be a struct
to use it for GORM First()
function.
The code:
package main
import (
"fmt"
)
type Test struct {
Test string
}
var Models = map[string]interface{}{
"test": newTest(),
}
func main() {
test1 := Test{}
fmt.Println("Test 1: ")
fmt.Printf("%v", test1)
fmt.Println()
fmt.Println("Test 1 as pointer: ")
fmt.Printf("%v", &test1)
fmt.Println()
test2 := Models["test"]
fmt.Println("Test 2: ")
fmt.Printf("%v", test2)
fmt.Println()
fmt.Println("Test 2 as pointer: ")
fmt.Printf("%v", &test2)
}
func newTest() Test {
var model Test
return model
}
According to the Size and alignment guarantees as per golang docs
This is why
Test 1
is&{}
Test2
is aninterface{}
, Test2 thus has pointer to information about type stored and pointer to the data itself. It Type and Value informationsTL;DR: In the first case you pass a value of type
*Test
for printing, but in the second case you pass a value of type*interface{}
! The%v
verb means to format using the default formatting, but the default formatting depends on the type of the value.The difference you see is just the default formatting rules of the
fmt
package's implementation.You're using
fmt.Printf()
:which takes a format string and other arguments as type
interface{}
. So note that if the value you pass is not of typeinterface{}
, the value will be wrapped in a value of typeinterface{}
.Now let's see your examples:
test1
is of typeTest
, and you pass&test1
which is of type*Test
. This will be wrapped in aninterface{}
. The formatting rules from the package doc offmt
:Since it is a pointer to a
struct
, the&{}
format will be used.Test
has a fieldTest string
, but you didn't set its value, so it defaults to the zero value of the typestring
which is the empty string""
. That's why you see nothing when displayed. Note that if you would have initialized it like this:The output would have been:
Let's see your 2nd example:
The first line is a short variable declaration, type of
test2
will be inferred from the right-hand side expression. The right hand side expression is an index expression, indexing a map. Its type will be the value type of the map, and since type ofModels
ismap[string]interface{}
, type oftest2
will beinterface{}
.So far so good. But what happens when you try to print it like
fmt.Printf("%v", &test2)
? You pass a pointer totest2
which is of typeinterface{}
, so what you pass is of type*interface{}
, and since this is not identical tointerface{}
, it will be wrapped in anotherinterface{}
value.So what gets passed to
fmt.Printf()
is aninterface{}
value, wrapping a*interface{}
value being the address of thetest2
variable.And now the formatting rule that applies here:
Since the value to be formatted is a pointer (
*interface{}
),%v
will default to%p
, which is:So the result is properly printing the address value in hexadecimal format, e.g.:
To obtain a struct from
test2
, you can use type assertion. So it should rather be something like this:This
test2
has identical type to that oftest1
, and will produce the same result when printing. Try it on the Go Playground.Best would be though to store
*Test
values in the map, and so no type assertion or even storing in local variable would be necessary, as theinterface{}
stored in the map would already be a pointer toTest
, which can be used / passed around as-is.