Today I’m live streaming again at the regular time. Last week I missed, due to some hardware problems. But I’m back up and running! Join me as I go through boot.dev’s “Learn Web Servers” course that I had planned for last week. I hope you can join me
Closures are a common concept in many langauges. If you’ve used them before, there’s nothing really new or interesting about the way Go handles them. But if you’re not familiar, here’s an introduction!
Function literals
…
Function literals are closures: they may refer to variables defined in a surrounding function. Those variables are then shared between the surrounding function and the function literal, and they survive as long as they are accessible.
Let me illustrate with an over-engineered version of Hello World:
func main() {
hello := lazyFormat("World") // hello is of type `func() string`
message := hello() // Here we call `hello()`, which formats the two closed-over variables
fmt.Println(message) // Finally we print the message
}
func lazyFormat(name string) func() string {
greeting := "Hello"
return func() string { // This func literal creates a closure over `name` and `greeting`
return strings.Join([]string{name, greeting}, ", ")
}
}
If this is all gibberish to you, let me show you the code once again, this time illustrating the flow of control:
func main() {
hello := lazyFormat("World") // 1: We call lazyFormat() with the argument "World"
message := hello() // 4: We need the output of `hello()` to assign to message
fmt.Println(message) // 6: Display the message
}
func lazyFormat(name string) func() string {
greeting := "Hello" // 2: We assign value "Hello" to variable `greeting`
return func() string { // 3: We return an anonymous function. It's not executed yet!
return strings.Join([]string{name, greeting}, ", ") // 5: Evaluate the message to return
}
}
Quotes from The Go Programming Language Specification Version of August 2, 2023