为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
MYYA 2021-07-02 10:11:54
在下面的代码片段中,我想了解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}
查看完整描述

3 回答

?
吃鸡游戏

TA贡献1829条经验 获得超7个赞

你问为什么


iPerson = person

iPerson = &person

被允许。它们都是允许的,因为 person 和 &person 都实现了 IPerson 接口。这是显而易见的,因为 IPerson 是空接口——每个值都实现它。


确实,您无法静态确定 IPerson 的值是持有指针还是值。所以呢?关于 IPerson,您只知道存储在该类型值中的任何对象都实现了接口中的方法列表。假设这些方法已正确实施。IPerson 是否持有值或指针与此无关。


例如,如果该方法要更改存储在对象中的某些内容,那么该方法几乎必须是一个指针方法,在这种情况下,只能在接口类型的变量中存储一个指针值。但是如果没有任何方法改变存储在对象中的内容,那么它们都可以是值方法,并且可以在变量中存储非指针值。


查看完整回答
反对 回复 2021-07-05
?
哆啦的时光机

TA贡献1779条经验 获得超6个赞

当您执行以下行时:

iPerson = person

您正在Person接口变量中存储一个值。由于对结构的赋值执行复制,是的,您的代码正在复制。要从接口内部检索结构,您需要获取另一个副本:

p := iPerson.(Person)

所以你很少想用可变类型来做这件事。如果您想在接口变量中存储指向结构的指针,则需要显式执行此操作:

iPerson = &person

就引擎盖下发生的事情而言,接口变量分配堆空间来存储大于指针的值是正确的,但这通常对用户不可见。


查看完整回答
反对 回复 2021-07-05
  • 3 回答
  • 0 关注
  • 269 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信