为什么我不能使用指向期望* interface {}的特定类型的指针?

时间:2017-07-01 19:44:53

标签: pointers go typechecking

我有以下功能:

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

我使用它来获取进出boltdb的struct数据。我想做的是将签名更改为:

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

然后我希望能够像这样调用它(b在这种情况下是一个gob编码的Account

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

但是当我这样做时,我会收到类似Cannot use *Account for type *interface{}的错误。

目前,我刚刚将其更改为interface{}。但是,如果我直接传入Account或其他类型而不使其成为指针,gob会抛出错误。看起来这应该在编译时可以检查。并且假设interface{}类型的参数接受任何内容,为什么类型*interface{}的参数不接受指向任何东西的指针?

2 个答案:

答案 0 :(得分:5)

Go中接口类型的通用性未传递给派生类型。这适用于指针(如您所注意到的),也适用于切片,通道等。例如,您无法将[]string分配给[]interface{}

有多种方法可以解释这一点。对于Haskell程序员:

Go没有协变或逆变类型。所有类型构造函数(例如创建指针类型的*)都是不变的。因此,即使Account*Account(以及所有其他类型)都是interface{}的子类型,也不会是*interface{}[]interface{}的子类型。这有时不方便,但它使Go的类型系统和可分配性规则更加简单。

对于C程序员:

interface{}可以保存任何类型的值,但不会直接保留它。它不是一个可变大小的魔术容器,而是一个由指向类型的指针和指向值的指针组成的结构。将具体类型分配给interface{}时,将填写这两个字段。*interface{}是指向其中一个结构的指针。当您尝试将*Account分配给*interface{}时,无处可放置类型信息,因为*interface{}是一个只包含指针的单个机器字。所以编译器不允许你这样做。

答案 1 :(得分:1)

interface{}也可以包含一个没有问题的指针。 但没有什么比指向interface{}

的指针更像了

见这些:

Cast a struct pointer to interface pointer in Golang

Why can't I assign a *Struct to an *Interface?