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

给接口赋值会复制任何东西吗?

尚河
2023-03-14
问题内容

我一直在努力围绕Go中接口的概念。

唯一让我感到不适的是语法。看下面的例子:

package main

import "fmt"

type Interface interface {
    String() string
}

type Implementation int

func (v Implementation) String() string {
    return fmt.Sprintf("Hello %d", v)
}

func main() {
    var i Interface
    impl := Implementation(42)
    i = impl
    fmt.Println(i.String())
}

我的问题是i = impl。基于一个接口实例实际上拥有一个指向实际数据的指针引用这一事实,我觉得这样做很自然i = &impl。通常,在不使用时分配非指针&将创建数据的完整内存副本,但是在分配给接口时,这似乎避开了它,而是 简单地(在幕后)将指针分配给接口值。
我对吗?
也就是说,用于的数据int(42)会不会复制到内存中?


问题答案:

的数据int(42) 被复制。试试这个代码:

func main() {
    var i Interface
    impl := Implementation(42)
    i = impl
    fmt.Println(i.String())
    impl = Implementation(91)
    fmt.Println(i.String())
}

(游乐场链接)

您会发现第二个i.String()仍然显示42。Go的棘手方面之一可能是方法接收者也可以是指针。

func (v *Implementation) String() string {
    return fmt.Sprintf("Hello %d", *v)
}

// ...
i = &impl

如果要接口保留指向的原始值的指针,这就是您想要的impl。接口“内部”是一个结构,它持有指向某些数据或数据本身(以及一些我们可以出于目的而忽略的类型元数据)的指针。如果数据本身的大小小于或等于一个机器字(无论是指针,结构还是其他值),则将存储数据本身。

否则它将是指向某些数据的指针,但这是棘手的部分:如果实现接口的类型是struct,则指针将指向struct的 副本
,而不是分配给接口变量本身的struct。或至少在语义上用户可以这样认为,优化可以允许在两个值分开之前(例如,直到您调用String或重新分配impl)才复制该值。

简而言之:分配给接口可以在语义上被认为是实现接口的数据的副本。如果这是指向类型的指针,则复制该指针,如果是大结构,则复制该大结构。在后台使用指针的接口的详细信息是出于垃圾收集的原因,并确保堆栈以可预测的数量扩展。就开发人员而言,应将它们视为分配的实现类型的特定实例的语义副本。



 类似资料:
  • 问题内容: 我在将任何内核模块构建到我的机器上时遇到问题。每当我构建模块时,modpost总是说模块为零: 为了解决该问题,我编写了一个测试模块(hello.c): 这是模块的Makefile: 在计算机上构建它时,得到以下输出: 当我在另一台机器上制作模块时,它成功了: 我寻找了有关modpost的任何相关文档,但收效甚微。任何人都知道modpost如何决定要构建什么?我可能会缺少一个环境吗?

  • 我有一个简单的模板结构将字符串与值关联起来 我有一个函数,我希望接受1个或多个任何类型的字段,这些字段可能是不同的类型,所以我使用,因为据我所知,C++缺少类型化变量参数,不能确定变量参数的大小,并且必须至少有一个其他参数来确定从哪里开始。 问题是我不知道如何告诉它接受可能是不同类型的字段。在Java中,我只使用,但是C++缺少类型化变量参数和通配符。我唯一的另一个想法是使参数类型为,但这似乎是一

  • 本文摘自flappy bird娱乐教程的第6天--http://www.kilobolt.com/day-6-adding-graphics---welcome-to-the-necropolis.html 这是我在游戏中使用的纹理图像文件。它是一个256px64px.png文件。 这里是我用来加载纹理的类,以及我希望SpriteBatch绘制的特定的TextureRegion(纹理的一部分)。

  • 问题内容: 如何在Go中复制接口值? 我的界面: 我的结构: 我尝试复制的值。 主功能: 如何实现更改副本名称的原件不变? 问题答案: 这里的问题是,你的变量(类型为)持有 指向 一个结构。 当您分配给另一个变量(类型)时,将复制作为动态类型和值对的接口值- 因此将复制指向同一结构的指针。所以,你只能有一个结构值,二者并指(点)到这一点。通过任何接口值更改它都会更改一个值和唯一值。 为了与不同的,

  • 我至少一个月没更新任何东西了。我刚刚正常工作,突然菜单都是空白的,所以我决定重新启动eclipse。我单击“关闭”和“确定”保存所有内容,但什么也没发生,所以我再次单击“关闭”并关闭eclipse。我点击eclipse,加载屏幕只会闪烁并消失,然后出现一条消息,告诉我检查

  • 我是不是漏了什么? 这不能编译。Eclipse抱怨"Matcher Asrett类型中的方法断言(T, Matcher)不适用于参数(int, Matcher 我错过了什么东西可以用吗?我在过去使用过其他Hamcrest方法...那么这有什么不同呢?