【发布时间】:2023-03-06 00:37:01
【问题描述】:
在下面的代码 sn-p 中,我想了解在 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
}
(这个问题是我对我对why runtime error on io.WriterString? 的回答的准确事实正确性重新考虑的结果。所以我决定尝试做一些调查,以了解接口变量和对它们的分配究竟是如何工作的在 Go 中。)
编辑:在收到一些有用的答案后,我仍然对此感到困惑:
iPerson = person
iPerson = &person
——两者都是合法的。然而,对我来说,这提出了一个问题,为什么编译器允许这种弱类型发生?上面的一个含义是:
iPerson = &person
var person2 = iPerson.(Person) # panic: interface conversion: interface is *main.Person, not main.Person
而更改第一行可以解决问题:
iPerson = person
var person2 = iPerson.(Person) # OK
...因此无法静态确定iPerson 是否持有指针或值;似乎任何东西都可以在运行时为其分配任何一个而不会引发错误。为什么会做出这样的设计决定?它的用途是什么?它绝对不符合“类型安全”的心态。
【问题讨论】:
标签: go pointers interface compilation