go - 为什么存储在接口(interface)中的值在 Golang 中不可寻址

标签 go

引用 golang wiki ( https://github.com/golang/go/wiki/MethodSets#interfaces ):

“存储在接口(interface)中的具体值是不可寻址的,就像 map 元素不可寻址一样。”

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

但是,接口(interface)方面还不清楚。为什么它们不可寻址?这是因为一些硬设计假设吗?

最佳答案

为什么存储在接口(interface)中的非指针值不可寻址?这是一个很好的问题,答案解释了为什么包含非​​指针值的接口(interface)不能成为具有指针接收器的方法的接收器,从而导致可怕的错误:

<type> does not implement <interface> (<name> method has pointer receiver)

tl;dr

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

因为存储在接口(interface)中的非指针值不可寻址,编译器无法将其地址传递给具有指针接收器的方法。

长答案

我在网上看到的答案没有多大意义。例如,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”).

的确,存储在接口(interface)中的值是不可寻址的,但据我所知,这不是因为它存储在“隐藏的内存位置”。

另一个常见的答案是:

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).

这是没有意义的,因为指向复制到接口(interface)中的值的指针与指向复制到具体类型中的值的指针没有区别;在这两种情况下,您都无法通过指向副本的指针更改原始复制值。

那么为什么存储在接口(interface)中的值不可寻址?如果它可寻址,答案就在于后续影响。

假设您有一个接口(interface)I,以及两种类型A< em>B,满足那个接口(interface):

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)

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

    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/strong> 现在包含 BaPtr 不再是指向 A

但是,这是允许的:

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

因为第二行复制了 i.(A)aPtr 中的值不指向 i.(A)

那么,为什么包含非​​指针值的接口(interface)不能成为具有指针接收者的方法的接收者呢?因为存储在接口(interface)中的非指针值不可寻址,所以编译器无法将其地址传递给具有指针接收器的方法。

关于go - 为什么存储在接口(interface)中的值在 Golang 中不可寻址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48790663/

相关文章:

go - 是否可以使用bufio.Writer进行使用/写入?

去安装不工作

go - 通过 vagrant GO 进行远程调试

go - 如何从 Go 服务器在浏览器中下载文件

regex - 去标志 : trailing slash escapes quote on Windows

list - 在 go 中创建一个包含列表类型的结构

windows - 使用WINAPI找出特殊文件上的进程事件句柄(锁定)

regex - Go-lang 使用正则表达式时出错

docker - 如何将 ffmpeg 命令安装到我的 docker 中

go - 使用 GO 进行 AWS SNS 签名验证