sta*_*art 4 arrays struct pointers compare go
我不知道为什么下面发生了,我找不到相关的源代码.谁能向我解释一下?
var s, ss struct{} // two empty structs
arr1 := [6]*struct{}{&s} // array with empty struct pointer
arr2 := [6]*struct{}{&ss} // array with empty struct pointer
fmt.Println(&s == &ss, arr1 == arr2) // false, true
var l, ll struct{A int}{}
arr3 := [6]*struct{A int}{&l} // array with empty struct pointer
arr4 := [6]*struct{A int}{&ll} // array with empty struct pointer
fmt.Println(&l == &ll, arr3 == arr4) // false, false
Run Code Online (Sandbox Code Playgroud)
指针值具有可比性.如果两个指针值指向同一个变量或两者都有值,则它们相等
nil.指向不同零大小变量的指针可能相同也可能不相等.
如果结构或数组类型不包含大小大于零的字段(或元素),则其大小为零.两个不同的零大小变量在内存中可能具有相同的地址.
在大小s和ss变量是零,因此&s和&ss是指向不同的大小为零的变量,因此该规范并不能保证他们平等的东西.这意味着&s == &ss可以评估为true或者false,你不能指望结果是什么,这样做是错误的.
尽管如此,在应用程序的单个运行时期间,一旦它们相等,一旦它们不相同,这就很奇怪了.教训是永远不要依赖它.
通过查看逃逸分析可以解释不同的行为.
让我们简化您的应用程序:
var s, ss struct{} // two empty structs
arr1 := [6]*struct{}{&s} // array with empty struct pointer
arr2 := [6]*struct{}{&ss} // array with empty struct pointer
fmt.Println(&s == &ss, arr1 == arr2) // false, true
Run Code Online (Sandbox Code Playgroud)
运行转义分析go run -gcflags '-m' play.go给出:
./play.go:13:17: &s == &ss escapes to heap
./play.go:13:30: arr1 == arr2 escapes to heap
./play.go:11:23: main &s does not escape
./play.go:12:23: main &ss does not escape
./play.go:13:14: main &s does not escape
./play.go:13:20: main &ss does not escape
./play.go:13:13: main ... argument does not escape
false true
Run Code Online (Sandbox Code Playgroud)
&s并且&ss不要逃避(因为它们没有传递给fmt.Println(),只有结果&s == &ss).
如果我们在上面简化的应用中添加一行:
var s, ss struct{} // two empty structs
arr1 := [6]*struct{}{&s} // array with empty struct pointer
arr2 := [6]*struct{}{&ss} // array with empty struct pointer
fmt.Println(&s == &ss, arr1 == arr2) // true, true
fmt.Printf("%p %p\n", &s, &ss) // true, true
Run Code Online (Sandbox Code Playgroud)
运行逃逸分析现在给出:
./play.go:13:17: &s == &ss escapes to heap
./play.go:13:30: arr1 == arr2 escapes to heap
./play.go:15:24: &s escapes to heap
./play.go:15:24: &s escapes to heap
./play.go:10:6: moved to heap: s
./play.go:15:28: &ss escapes to heap
./play.go:15:28: &ss escapes to heap
./play.go:10:9: moved to heap: ss
./play.go:11:23: main &s does not escape
./play.go:12:23: main &ss does not escape
./play.go:13:14: main &s does not escape
./play.go:13:20: main &ss does not escape
./play.go:13:13: main ... argument does not escape
./play.go:15:12: main ... argument does not escape
true true
Run Code Online (Sandbox Code Playgroud)
行为改变了:我们现在看到true true输出(在Go Playground上试试).
改变行为的原因是因为&s并且&ss转移到堆:它们被直接传递给fmt.Println(),因此编译器改变了它们的存储方式(地址),并且随之改变了它们的地址.
请参阅相关/可能重复:空结构切片的Golang地址
| 归档时间: |
|
| 查看次数: |
60 次 |
| 最近记录: |