TL; DR:在你傳遞*Test
類型的值用於打印的第一種情況,但是在第二種情況下你傳遞*interface{}
類型的值! %v
動詞表示使用默認格式設置格式,但默認格式取決於值的類型。
你看到的區別只是默認格式化fmt
包的實施細則。
您使用fmt.Printf()
:
func Printf(format string, a ...interface{}) (n int, err error)
這需要一個格式字符串和其他參數作爲interface{}
類型。因此,請注意,如果您傳遞的值不是interface{}
類型的值,則該值將被包裝爲類型爲interface{}
的值。
現在讓我們看看你的例子:
test1 := Test{}
// ...
fmt.Printf("%v", &test1)
test1
是Test
型的,和你通過&test1
這是*Test
類型。這將被包裹在一個interface{}
。從fmt
封裝文檔的格式規則:
對於化合物目的,元件使用這些規則印刷,遞歸地,佈置是這樣的:
struct: {field0 field1 ...}
array, slice: [elem0 elem1 ...]
maps: map[key1:value1 key2:value2]
pointer to above: &{}, &[], &map[]
既然是一個指針,指向一個struct
,將使用&{}
格式。 Test
的字段爲Test string
,但未設置其值,因此它默認爲類型爲string
的zero value,這是空字符串""
。這就是爲什麼你顯示時什麼也看不到。請注意,如果你會喜歡這個初始化它:
test1 := Test{"a"}
輸出本來:
&{a}
讓我們看看你的第二個例子:
test2 := Models["test"]
// ...
fmt.Printf("%v", &test2)
第一行是short variable declaration ,test2
的類型將從右邊的表達式中推斷出來。右側表達式是index expression,爲地圖編制索引。其類型將是地圖的值類型,並且由於Models
的類型爲map[string]interface{}
,因此test2
的類型將爲interface{}
。
到目前爲止這麼好。但是當你試圖像fmt.Printf("%v", &test2)
那樣打印時會發生什麼?你傳遞一個指向test2
的指針,它的類型爲interface{}
,所以你通過的是*interface{}
,因爲這與interface{}
不一樣,所以它會被包裝在另一個interface{}
的值中。
那麼傳遞給fmt.Printf()
的值是interface{}
的值,將*interface{}
值作爲test2
變量的地址。
而現在,在這裏適用的格式規則:
爲%V的默認格式爲:
bool: %t
int, int8 etc.: %d
uint, uint8 etc.: %d, %x if printed with %#v
float32, complex64, etc: %g
string: %s
chan: %p
pointer: %p
由於要格式化的值是一個指針(*interface{}
),%v
將默認爲%p
,即:
Pointe R:
%p base 16 notation, with leading 0x
所以結果是正確打印十六進制格式的地址值,例如:
0x1040a160
從test2
獲得一個結構,你可以使用type assertion。所以它應該是這樣的:
t2 := Models["test"]
test2 := t2.(Test) // test2 is of type Test
這test2
具有相同類型到的test1
,並在打印時會產生相同的結果。試試Go Playground。
最佳將是雖然存儲*Test
值在地圖,所以沒有類型斷言或偶存儲在局部變量將是必要的,因爲存儲在地圖的interface{}
將已經是指向Test
,其可用於/按照原樣傳遞。
你應該在這裏粘貼代碼。簡而言之,'test1'具有'Test'類型,'test2'具有'interface {}'類型(a.k.a空接口)。這是一種不同的類型。 – ymonad
@ymonad是的,我檢查了它,但我怎樣才能將它返回到正確的結構? – PumpkinSeed
當然,您可以將'map [string] interface {}'更改爲'map [string] Test'。不過,我想這是[XY問題](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。你有沒有想要解決的具體問題? – ymonad