October 16, 2023

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’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

Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .