【问题标题】:Why can't I use a pointer to a specific type where *interface{} is expected?为什么我不能使用指向需要 *interface{} 的特定类型的指针?
【发布时间】:2017-12-05 11:53:57
【问题描述】:

我有以下功能:

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 在这种情况下是一个 gob 编码的Account

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

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

目前,我刚刚将其改回interface{}。但是,如果我直接传入 Account 或其他类型而不将其设为指针,gob 会引发错误。似乎这应该在编译时进行检查。既然interface{} 类型的参数可以接受任何东西,为什么*interface{} 类型的参数不接受指向任何东西的指针?

【问题讨论】:

    标签: pointers go typechecking


    【解决方案1】:

    Go 中接口类型的通用性不会传递给派生类型。这适用于指针(如您所见),也适用于切片、通道等。例如,您不能将 []string 分配给 []interface{}

    有多种解释方式。对于 Haskell 程序员:

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

    对于 C 程序员:

    interface{} 可以保存任何类型的值,但它不直接保存它。它不是一个可变大小的魔法容器,它只是一个由指向类型的指针和指向值的指针组成的结构。当您将具体类型分配给interface{} 时,这两个字段都会被填写。*interface{} 是指向这些结构之一的指针。当您尝试将*Account 分配给*interface{} 时,没有地方可以放置类型信息,因为*interface{} 是一个仅包含一个指针的机器字。所以编译器不会让你这样做。

    【讨论】:

    • 喜欢 Haskell / C 对比的极端。
    【解决方案2】:

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

    查看这些:

    Cast a struct pointer to interface pointer in Golang

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-26
      • 2013-10-18
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 2010-10-28
      • 1970-01-01
      相关资源
      最近更新 更多