在下面的代码片段中,我想了解在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
}
(这个问题是我对为什么 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
保存指针或值;似乎任何东西都可以在运行时为其分配任何一个而不会引发错误。为什么会做出这样的设计决定?它的用途是什么?它绝对不符合“类型安全”的心态。