top | item 29193038

(no title)

jdreaver | 4 years ago

Making a closure usually requires allocation. For example:

    package main

    import "fmt"

    func main() {
        closure := make_closure()
        fmt.Println("closure():", closure())
    }

    func make_closure() func() int {
        x := 1
        return func() int { return x }
    }
This prints:

    $ go run main.go
    closure(): 1

If x were allocated on the stack, it would get nuked after we returned from make_closure(). In Rust you could move x to the closure, but I think in this Go example x would be heap allocated, assuming the Go compiler doesn't notice it can inline all of this and avoid allocating. Maybe assume a more complex example with a struct that had to be computed via a function argument or something :)

discuss

order

kgeist|4 years ago

Oh yes, closures too. Coming from C++ background, you kinda intuitively understand when things escape and when they don't, because you assume that Go would implement it in the most straightforward way (like it usually does), and in the case of closures, heap-allocating a captured variable is the simplest implementation (just let GC handle it!) considering the implicit reference semantics (that you can change "x" anywhere outside of the closure and it should be immediately visible in the closure, too). I.e. assume the worst (and don't expect Go to do some clever special-casing similar to move semantics in C++/Rust), and it's often the right answer :)