2017-07-01 98 views
0

我有以下功能:爲什麼我不能使用指向* interface {}的特定類型的指針?

func bytesToData(data interface{}, b []byte) error { 
    buf := bytes.NewBuffer(b) 
    dec := gob.NewDecoder(buf) 
    return dec.Decode(data) 
} 

我用這個進出boltdb的獲得結構數據。我想要做的,就是改變這種簽名:

func bytesToData(data *interface{}, b []byte) error 

然後,我希望能夠這樣稱呼它(b在這種情況下是採空區編碼Account

acc := &Account{} 
err := bytesToData(acc, b) 

但是當我這樣做,我得到一個錯誤,如Cannot use *Account for type *interface{}

現在,我剛剛將其更改回interface{}。但是,如果我直接傳入Account或其他某種類型而不使其成爲指針,則gob會拋出錯誤。這似乎應該在編譯時檢查。並且假設類型爲interface{}的參數接受任何內容,爲什麼*interface{}類型的參數不接受指向任何內容的指針?

回答

3

在Go接口類型的通用性不上派生類型傳遞。這適用於指針(如您注意的),以及切片,通道等。例如,您不能將[]string分配給[]interface{}

有多種方式可以解釋這一點。對於Haskell程序員:

Go沒有協變或逆變類型。所有類型的構造函數(如創建指針類型的*)都是不變的。因此即使Account*Account(以及所有其他類型)都是interface{}的子類型,但是*interface{}[]interface{}的子類型均不是。這有時不方便,但它使Go的類型系統和可分配性規則更加簡單。

對於C程序員:

interface{}可以容納任何類型的值,但它不直接將其保持。它不是一個可變大小的魔法容器,它只是一個由指向類型的指針和指向值的指針組成的結構。當您將具體類型分配給interface{}時,這兩個字段都將被填充。*interface{}是指向其中一個結構的指針。當您嘗試將*Account指定給*interface{}時,無法放置類型信息,因爲*interface{}是一個只包含指針的單個機器字。所以編譯器不會讓你這樣做。

+0

愛上Haskell/C對比的極端。 –

相關問題