我正在阅读一本名为《 Go编程语言》的书,在有关指针的第二章中,写了以下内容

It is perfectly safe for a function to return the address of a local variable. For instance, in the
code below, the local variable v created by this particular call to f will remain in existence even
after the call has returned, and the pointer p will still refer to it:

1
2
3
4
5
var p = f()
func f() *int {
    v := 1
    return &v
}

我完全不明白这一点,应该在执行函数后销毁局部变量。是因为可能v是在堆上分配的。我知道在C中是否使用malloc分配空间,函数执行后它不会被销毁,因为它在堆上。

  • Go不是C。Go具有垃圾收集器,可以为您管理内存。
  • 在Go中,"局部"变量的工作方式与在C语言中的工作方式不同。变量是在堆栈中分配还是在堆中分配,是由编译器在编译时根据转义分析确定的,而不仅仅是基于其指针还是指针不是(因为它在C中)。一般来说,您可以简单地信任Gos垃圾收集器。它会为您管理内存,该语言通常会阻止您可以访问陈旧指针或未分配内存的情况(Go中的段错误通常来自尝试访问nil指针)。
  • 访问nil指针永远不会出现段错误,但会触发panic
  • 实际上,SIGSEGV被认为是分段错误,或者是由无效的内存引用引起的错误,无论您如何称呼它。
  • 局部变量是指变量的范围,而不是值的分配方式。该规范没有详细说明所有变量的分配。

Go不是C。尽管有相似之处,但它的层次更高。它利用了带有绿色线程调度程序和垃圾收集内存管理器的完整运行时。只要有实时引用,它就永远不会收集内存。

Go编译器包括一个称为"转义分析"的阶段,在该阶段中,它跟踪每个变量以查看是否"转义"了声明其的函数。任何可以转义的值都分配在堆上,并由垃圾回收管理;否则,它通常分配在堆栈上。

您可以找到有关该主题的更多信息:

  • https://blog.golang.org/ismmkeynote
  • https://dave.cheney.net/2014/06/07/five-things-that-make-go-fast
  • https://dougrichardson.org/2016/01/23/go-memory-allocations.html
  • https://www.agardner.me/golang/garbage/collection/gc/escape/analysis/2015/10/18/go-escape-analysis.html
  • https://www.ardanlabs.com/blog/2017/05/language-mechanics-on-escape-analysis.html
  • 请问您有什么资料可以使我学到更多吗?
  • 刚刚添加了一些参考。