为什么存储在接口中的值在Golang中无法寻址

前端之家收集整理的这篇文章主要介绍了为什么存储在接口中的值在Golang中无法寻址前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
引用golang wiki( https://github.com/golang/go/wiki/MethodSets#interfaces):

“存储在接口中的具体值不可寻址,就像地图元素不可寻址一样.”

这里解释了地图值不可寻址的问题:
Why are map values not addressable?

但是,关于界面还不清楚.他们为什么不能解决?这是因为一些硬设计假设吗?

为什么接口中存储的非指针值不可寻址?这是一个很好的问题,答案解释了为什么包含非​​指针值的接口不能成为带有指针接收器的方法的接收器,从而导致可怕的错误
<type> does not implement <interface> (<name> method has pointer receiver)

TL;博士

存储在接口中的非指针值不可寻址以维持类型完整性.例如,当接口中随后存储不同类型B的值时,指向A的指针(其指向接口中的类型A的值)将无效.

由于存储在接口中的非指针值不可寻址,因此编译器无法将其地址传递给具有指针接收器的方法.

答案很长

我在网上看到的答案没有多大意义.例如,this article说:

The reason is that the value in an interface is in a hidden memory
location,and so the compiler can’t automatically get a pointer to
that memory for you (in Go parlance,this is known as being “not
addressable”).

存储在接口中的值确实是不可寻址的,但据我所知,并不是因为它存储在“隐藏的存储位置”中.

另一个常见的答案是:

When an interface value is created,the value that is wrapped in the interface is copied. It is therefore not possible to take its address,and even if you did,using a pointer to the interface value would have unexpected effects (ie. unable to alter the original copied value).

这没有任何意义,因为指向复制到接口中的值的指针与指向复制到具体类型的值的指针没有什么不同;在这两种情况下,您都无法通过指向副本的指针更改原始复制值.

那么为什么存储在接口中的值不可寻址?如果它是可解决的,答案就在于后续影响.

假设您有一个接口I,以及满足该接口的两种类型A和B:

type I interface{}
type A int
type B string

创建一个A并将其存储在I中:

func main() {
    var a A = 5
    var i I = a
    fmt.Printf("i is of type %T\n",i)

让我们假设我们可以获取存储在接口中的值的地址:

var aPtr *A
    aPtr = &(i.(A)) // not allowed,but if it were...

现在创建一个B并将其存储在i中:

var b B = "hello"
    i = b
    fmt.Printf("i is of type %T,aPtr is of type %T\n",i,aPtr)
}

这是输出

i is of type main.A
i is of type main.B,aPtr is of type *main.A

将B放入i之后,aPtr指向什么? aPtr被声明为指向A,但是t现在包含一个B,而aPtr不再是指向A的有效指针.

但是,允许这样做:

var aPtr *A
    var a2 A = i.(A)
    aPtr = &a2

因为第二行在i.(A)中复制了值,而aPtr没有指向i.(A).

那么,为什么包含非​​指针值的接口不能成为带指针接收器的方法的接收器呢?由于存储在接口中的非指针值不可寻址,因此编译器无法将其地址传递给具有指针接收器的方法.

猜你在找的Go相关文章