在下面的代码片段中,我想知道当其内容仍未初始化时,究竟存储在iPerson
中的数据是什么:只有0字节的值?或者它实际上是一个隐藏的指针(当然也初始化为0字节)?无论如何,在iPerson = person
究竟发生了什么?Go中的接口变量究竟如何实现?
如果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?的确切事实的正确性有第二个想法的结果,所以我决定尝试做一些调查,了解它是如何正是接口变量和任务对他们在工作围棋)
编辑:收到了一些有用的答案后,我还是不解与此:
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允许'iPerson =&person'以及'iPerson = person'而不必改变'iPerson'的类型。它允许运行时类型的错误,而不是静态捕获。 Volker指出的这篇文章并没有提到,甚至没有提到。 –
如果您将结构视为不可变的值,那么按值传递它可能会很有意义。在实践中,如果你定义了接收指针的方法,你可能不会混淆它们,因为这些方法将无法访问接口值中保存的值,所以不会混淆:http:// play .golang。org/p/E_8WjLS4S0 –
好的,你说在实践中这不会成为问题吗?但我仍然认为这是语言设计中的不雅,类型系统可以在这里做得更好。 –