4 ms·
Learn about stack versus heap, and recognize that Go treats the stack differently from other languages. Note that the Go language spec does not even contain th
by danieldk 11y ago
Learn about stack versus heap, and recognize that Go treats the stack differently from other languages.
Note that the Go language spec does not even contain the terms 'stack' and 'heap. Whether something is stack or heap-allocated isn't always clear. E.g. consider:
foo := &Foo{} // or: new(Foo)
This could be stack or heap-allocated (in the most popular Go implementation) depending on whether the compiler thinks it escapes or not.
- pcwalton 11y ago> Learn about stack versus heap, and recognize that Go treats the stack differently from other languages. Yeah, this comment strikes me as deeply confused. Go does not give you precise control over what goes on the stack versus the heap: it's even in the FAQ. There's a common misconception that stack vs. heap and value types vs. reference types represent the same distinction; they do not. For example, note that it is possible in unmanaged languages to have dangling references into the stack.
- masklinn 11y agoUnless I'm mistaken it is technically true though, AFAIK other languages fall in two broad groups * heap-based languages (vast majority of the high-level ones), everything is treated as heap-allocated, may be stack-allocated as an optimisation (while ensuring/conserving heap semantics)[0] * stack/heap languages, strict semantic separation between heap allocation and stack allocation, the developer decides whether values get heap-allocated or stack-allocated Go has the semantics separation of the latter (whether something is heap-allocated or stack-allocated had strong semantic significance and is not dependent on the thing's type) but the control of the former (the runtime decides and doesn't tell you) [0] a subset of these languages may have "value types" which have stack allocation semantics, that's linked to the type itself and the semantics are stable
- pcwalton 11y agoTo use your set of categories, Go is a fully heap-based language. Everything is semantically on the heap. Stack allocation semantics have to do with when the object is destroyed, which Go does not have any way to control in the language. Value vs. reference types are totally orthogonal. To see how this is true, try creating a value type (such as a struct or an array) in Go and capture a reference to it in an (escaping) closure to defeat the escape analysis optimization. The object will definitely be allocated on the heap.
- masklinn 11y agoThe issue I was referring to is is if you don't > capture a reference to it in an (escaping) closure to defeat the escape analysis optimization. the object absolutely doesn't behave as a heap-allocated value. So everything is not semantically on the heap.
- pcwalton 11y agoThree points: 1. There are many other things that can cause escape analysis to fail. You can also capture references to a value in an opaque function, send it over a channel, etc. etc. 2. There is no semantic difference between stack and heap (modulo when finalizers run). The only thing the language says is that object is guaranteed to be destroyed when it is no longer referenced. The compiler can fulfill this obligation sometimes through stack obligations, but that's done through a set of heuristics. The language says nothing about this (and the FAQ states this quite explicitly). 3. Java does the same thing. The HotSpot JVM will use escape analysis to perform SROA (which is an important optimization). Note that escape analysis is independent of value vs. reference types; Java has much fewer value types, but it can still do escape analysis. This is because value/reference and stack/heap are orthogonal.