我是 Go 新手,我在 C 风格的基于堆栈的编程(其中自动变量位于堆栈上,分配的内存位于堆上)与 Python 风格的基于堆栈的编程之间存在一些认知失调,其中唯一的存在于堆栈上的东西是指向堆上对象的引用/指针。
据我所知,以下两个函数给出相同的输出:
func myFunction() (*MyStructType, error) {
var chunk *MyStructType = new(HeaderChunk)
...
return chunk, nil
}
func myFunction() (*MyStructType, error) {
var chunk MyStructType
...
return &chunk, nil
}
即,分配一个新结构并返回它。
如果我用 C 语言编写,第一个会将对象放在堆上,第二个会将它放在堆栈上。第一个将返回一个指向堆的指针,第二个将返回一个指向堆栈的指针,在函数返回时它会消失,这将是一件坏事。
如果我用 Python(或除 C# 之外的许多其他现代语言)编写它,示例 2 将是不可能的。
我知道 Go 垃圾会收集这两个值,所以上述两种形式都很好。
报价:
请注意,与 C 不同,返回局部变量的地址是完全可以的;与变量关联的存储在函数返回后仍然存在。事实上,每次计算复合文字的地址时都会分配一个新的实例,因此我们可以将最后两行组合起来。
但它提出了几个问题。
-
在示例 1 中,结构是在堆上声明的。例子2呢?是在堆栈上以与在 C 中相同的方式声明还是在堆上进行声明?
-
如果示例 2 在堆栈上声明,那么它在函数返回后如何保持可用?
-
如果示例 2 实际上是在堆上声明的,那么结构是如何通过值而不是通过引用传递的?在这种情况下,指针的意义何在?