Method Expressions
For a type T
, T.M
is a function that is callable as a regular function with the same arguments as M
prefixed by an additional argument that is the receiver of the method
For example, given:
T.Mv
yields a function with the signaturefunc(tv T, a int) int
(*T).Mp
yields a function with the signaturefunc(tp *T, f float32) float32
(*T).Mv
yields a function with the signaturefunc(tv *T, a int) int
. This function indirects through the receiver to create a value to pass as the receiver to the underlying methodT.Mp
is illegal, because pointer-receiver methods are not in the method set of the value type
It is legal to derive a function value from a method of an interface type. The resulting function takes an explicit receiver of that interface type
Method Values
If x
has type T
, the method value x.M
is a function value that is callable with the same arguments as a method call of x.M
The expression x
is evaluated and saved during the evaluation of the method value; the saved copy is then used as the receiver in any calls, which may be executed later
For example, given:
t.Mv
yields a function value of typefunc(int) int
pt.Mp
yields a function value of typefunc(float32) float32
pt.Mv
is equivalent to(*pt).Mv
t.Mp
is equivalent to(&t).Mp
ift
is addressable
Capturing Values in Closures
Closures may refer to variables defined in a surrounding function (free variables). Those variables are then shared between the surrounding function and the closure, and they survive as long as they are accessible
Closed over variables semantically are always captured by address, meaning they escape to the heap
However, internally, a closure can be passed a copy of a value (not the address) to reduce GC pressure. For example, if the value is a constant or is never modified
Implementation
Direct Call
A compiler rewrites a direct call of a function literal into a normal function call with closure variables passed as arguments. This avoids allocation of a closure object
For example, this call:
becomes:
Function Values and Closure Object
Function values are pointers that point to structs. These structs contain either:
- Just the pointer to the function code for simple functions
- Pointers to an autogenerated wrapper function and receivers and/or function parameters in the case of method calls and closures
For example, this closure:
becomes:
References
- Go internals: capturing loop variables in closures - Eli Bendersky’s website
- Go internals: capturing loop variables in closures : r/golang
- How Golang Closures are layed out in memroy? : r/golang
- How are Go closures layed out in memory? - Stack Overflow
- go/src/cmd/compile/internal/walk/closure.go at master · golang/go · GitHub
- The Go Programming Language Specification - The Go Programming Language
- What is a Go function variable? · Phil Pearl’s Blog
- Methods in Go - Go 101