当前位置: 首页 > 面试题库 >

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

易昌翰
2023-03-14
问题内容

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

“以相同的方式,存储在接口中的具体值不可寻址,即映射元素不可寻址。”

但是,关于接口尚不清楚。为什么无法寻址?这是因为某些硬性设计假设吗?


问题答案:

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

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

tl; dr

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

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

长答案

我在网上看到的答案没有多大意义。例如,本文说:

原因是接口中的值位于隐藏的内存位置,因此编译器无法自动为您获取指向该内存的指针(按照Go的说法,这被称为“不可寻址”)。

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

另一个常见的答案是:

创建接口值时,将复制包装在接口中的值。因此,不可能获取其地址,即使这样做,使用指向接口值的指针也会产生意想不到的效果(即,无法更改原始复制的值)。

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

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

假设您有一个接口 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)

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



 类似资料:
  • 问题内容: 检查以下代码段: http://play.golang.org/p/xusdITxgT- 为什么会这样呢?因为我的论点之一必须是切片地址。 也许我没有对每个人都说清楚。 上面的代码就是为什么我需要一个分片地址。 结果变量在这里是我需要的。现在通常我可以做到 但是现在SomeStruct是动态的,我需要使用reflect.MakeSlice创建切片 而且它在上出错:结果必须是一个分片地址

  • 问题内容: 在Golang中,我们将结构体与接收器方法结合使用。到这里为止一切都很完美。 我不确定什么是接口。我们在结构中定义方法,如果要在结构上实现方法,则无论如何都要在另一个结构下再次编写该方法。 这意味着接口似乎只是方法定义,仅占用了页面上多余的空间。 有没有解释我为什么需要接口的示例? 问题答案: 接口太大了,不能在这里给出全面的答案,但是有些事情需要弄清楚它们的用途。 接口是一种 工具

  • 问题内容: 我读过(在TensorFlow中): a的值多次存储在内存中。 为什么将值多次存储在内存中? 问题答案: 因为恒定张量的数据已嵌入到图定义中。这意味着这些数据既存储在维护图定义的客户端中,又存储在运行时中,为所有张量分配其自己的内存。 IE浏览器,尝试 你会看到的 该场是原始内容,一样的。 现在,要查看运行时分配,可以使用运行。 如果您使用进行任何评估,都会看到类似的内容 这意味着运行

  • 问题内容: 我正在尝试使用GIT插件Jenkins拉出GIT的代码形式,并且该作业正在从属计算机上运行。 系统有 在系统中没有定义。 每当我在计算机上本地执行git clone时,它都能完美运行,但是从Jenkins那里我并没有成功。 它抛出以下错误: 是因为系统试图设置系统中不存在的http代理? 如果是,该如何预防? 或者,还有其他我想念的东西吗? 问题答案: 原来这是一个代理问题。 使用Je

  • 问题内容: 我正在阅读有关如何正确执行数组深拷贝的信息,但是我对如何实现数组感到困惑。它是该类的成员,但是,如果您阅读javadocs: 首先,如果此对象的类未实现Cloneable接口,则将引发CloneNotSupportedException。 那么为什么要首先定义方法呢?当然,如果仅当存在接口时才可以使用方法,则可以将方法放在接口中。该接口本身是空的; 它只是Java用来确保使用该方法合法

  • 我正在阅读如何正确执行数组的深度复制,但是我对是如何实现的感到困惑。它是类的成员,但是如果您阅读Javadocs: 首先,如果该对象的类没有实现接口Cloneable,则抛出CloneNotSupportedException。 为什么Java要这样做?我肯定他们有正当的理由,但我似乎想不通。