给接口赋值会复制任何东西吗? [英] Does assigning value to interface copy anything?

查看:48
本文介绍了给接口赋值会复制任何东西吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在努力围绕Go中接口的概念.阅读 this

I've been trying to wrap my head around the concept of interfaces in Go. Reading this and this helped a lot.

让我感到不舒服的唯一一件事就是语法.看看下面的示例:

The only thing that makes me uncomfortable is the syntax. Have a look at the example below:

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)的数据将不会复制到内存中吗?

My issue is with i = impl. Based on the fact that an interface instance actually holds a pointer reference to the actual data, it would feel more natural for me to do i = &impl. Usually assignment of non-pointer when not using & will make a full memory copy of the data, but when assigning to interfaces this seem to side-step this and instead simply (behind the scenes) assign the pointer to the interface value. Am I right? That is, the data for the int(42) will not be copied in memory?

推荐答案

将复制 int(42) 的数据.尝试以下代码:

The data for int(42) will be copied. Try this code:

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的棘手方面之一可能是方法的接收者也可以是指针.

You'll find that the second i.String() still shows 42. Perhaps one of the trickier aspects of Go is that method receivers can be pointers as well.

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

// ...
i = &impl

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

Is what you want if you want the interface to hold a pointer to the original value of impl. "Under the hood" an interface is a struct that either holds a pointer to some data, or the data itself (and some type metadata that we can ignore for our purposes). The data itself is stored if its size is less than or equal to one machine word -- whether it be a pointer, struct, or other value.

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

Otherwise it will be a pointer to some data, but here's the tricky part: if the type implementing the interface is a struct the pointer will be to a copy of the struct, not the struct assigned to the interface variable itself. Or at least semantically the user can think of it as such, optimizations may allow the value to not be copied until the two diverge (e.g. until you call String or reassign impl).

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

In short: assigning to an interface can semantically be thought of as a copy of the data that implements the interface. If this is a pointer to a type, it copies the pointer, if it's a big struct, it copies the big struct. The particulars of interfaces using pointers under the hood are for reasons of garbage collection and making sure the stack expands by predictable amounts. As far as the developer is concerned, they should be thought of as semantic copies of the specific instance of the implementing type assigned.

这篇关于给接口赋值会复制任何东西吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆