Go 中的接口变量究竟是如何实现的?

在下面的代码片段中,我想了解iPerson当其内容仍未初始化时究竟存储了什么:只是一个 0 字节的值?或者它实际上是引擎盖下的指针(当然也初始化为 0 字节)?在任何情况下,究竟发生了iPerson = person什么?


如果iPerson = person复制person,那么当一个实现IPerson但具有不同大小/内存占用的对象被分配给 时会发生iPerson什么?我的理解iPerson是一个存储在堆栈上的变量,所以它的大小必须是固定的。这是否意味着堆实际上是在底层使用的,所以iPerson实际上是作为指针实现的,但赋值仍然复制对象,如上面的代码所示?这是代码:


type Person struct{ name string }


type IPerson interface{}


func main() {

    var person Person = Person{"John"}

    var iPerson IPerson

    fmt.Println(person)  // => John

    fmt.Println(iPerson) // => <nil>  ...so looks like a pointer


    iPerson = person     //           ...this seems to be making a copy

    fmt.Println(iPerson) // => John


    person.name = "Mike"

    fmt.Println(person)  // => Mike

    fmt.Println(iPerson) // => John   ...so looks like it wasn't a pointer,

                         //           or at least something was definitely copied

}


MYYA
浏览 273回答 3
3回答

吃鸡游戏

你问为什么iPerson = personiPerson = &person被允许。它们都是允许的,因为 person 和 &person 都实现了 IPerson 接口。这是显而易见的,因为 IPerson 是空接口——每个值都实现它。确实,您无法静态确定 IPerson 的值是持有指针还是值。所以呢?关于 IPerson,您只知道存储在该类型值中的任何对象都实现了接口中的方法列表。假设这些方法已正确实施。IPerson 是否持有值或指针与此无关。例如,如果该方法要更改存储在对象中的某些内容,那么该方法几乎必须是一个指针方法,在这种情况下,只能在接口类型的变量中存储一个指针值。但是如果没有任何方法改变存储在对象中的内容,那么它们都可以是值方法,并且可以在变量中存储非指针值。

哆啦的时光机

当您执行以下行时:iPerson&nbsp;=&nbsp;person您正在Person接口变量中存储一个值。由于对结构的赋值执行复制,是的,您的代码正在复制。要从接口内部检索结构,您需要获取另一个副本:p&nbsp;:=&nbsp;iPerson.(Person)所以你很少想用可变类型来做这件事。如果您想在接口变量中存储指向结构的指针,则需要显式执行此操作:iPerson&nbsp;=&nbsp;&person就引擎盖下发生的事情而言,接口变量分配堆空间来存储大于指针的值是正确的,但这通常对用户不可见。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go