为什么我不能使用指向需要 *interface{} 的特定类型的指针?
Why can't I use a pointer to a specific type where *interface{} is expected?
我有以下功能:
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{}
类型的参数不接受指向任何东西的指针?
interface{}
也可以毫无问题地包含一个指针。
但是没有什么比指向 interface{}
的指针更好的了
查看这些:
Cast a struct pointer to interface pointer in Golang
Why can't I assign a *Struct to an *Interface?
Go 中接口类型的通用性不会传递给派生类型。这适用于指针(正如您所注意到的),也适用于切片、通道等。例如,您不能将 []string
分配给 []interface{}
.
对此有多种解释。对于 Haskell 程序员:
Go 没有协变或逆变类型。所有类型构造函数(例如创建指针类型的 *
)都是不变的。因此,即使 Account
和 *Account
(以及所有其他类型)是 interface{}
的子类型,也没有什么是 *interface{}
或 []interface{}
的子类型。这有时很不方便,但它使 Go 的类型系统和可分配性规则更加简单。
对于 C 程序员:
一个interface{}
可以保存任何类型的值,但它不会直接保存它。它不是一个可变大小的魔术容器,而只是一个由指向类型的指针和指向值的指针组成的结构。当您将具体类型分配给 interface{}
时,这两个字段都会被填充。*interface{}
是指向这些结构之一的指针。当您尝试将 *Account
分配给 *interface{}
时,没有地方可以放置类型信息,因为 *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
在这种情况下是一个 gob 编码的 Account
)
acc := &Account{}
err := bytesToData(acc, b)
但是当我这样做的时候,我得到了类似 Cannot use *Account for type *interface{}
.
现在,我刚刚将其改回 interface{}
。但是,如果我直接传入 Account
或其他类型而不将其设为指针,则 gob 会抛出错误。看起来这应该在编译时是可检查的。既然 interface{}
类型的参数接受任何东西,为什么 *interface{}
类型的参数不接受指向任何东西的指针?
interface{}
也可以毫无问题地包含一个指针。
但是没有什么比指向 interface{}
查看这些:
Cast a struct pointer to interface pointer in Golang
Why can't I assign a *Struct to an *Interface?
Go 中接口类型的通用性不会传递给派生类型。这适用于指针(正如您所注意到的),也适用于切片、通道等。例如,您不能将 []string
分配给 []interface{}
.
对此有多种解释。对于 Haskell 程序员:
Go 没有协变或逆变类型。所有类型构造函数(例如创建指针类型的 *
)都是不变的。因此,即使 Account
和 *Account
(以及所有其他类型)是 interface{}
的子类型,也没有什么是 *interface{}
或 []interface{}
的子类型。这有时很不方便,但它使 Go 的类型系统和可分配性规则更加简单。
对于 C 程序员:
一个interface{}
可以保存任何类型的值,但它不会直接保存它。它不是一个可变大小的魔术容器,而只是一个由指向类型的指针和指向值的指针组成的结构。当您将具体类型分配给 interface{}
时,这两个字段都会被填充。*interface{}
是指向这些结构之一的指针。当您尝试将 *Account
分配给 *interface{}
时,没有地方可以放置类型信息,因为 *interface{}
是一个只包含指针的机器字。所以编译器不会让你那样做。