跳转到主要内容
eLearner.app
模块 3 · 第 4 课(共 5)课程中的14/50~12 min
模块课程(4/5)

闭包和函数作为值

In Go, functions are first-class values: they can be assigned to variables, passed to other functions, and returned. A closure is a function literal (anonymous) that captures the variables of the environment in which it is defined.

Function literal

A function with no name, written inline. You call it immediately or assign it:

Go
greet := func(name string) {
    fmt.Println("ciao", name)
}
greet("Anna")

// invocata immediatamente:
func() { fmt.Println("subito") }()

The type of greet is func(string).

Capturing the environment: closure

The function literal can read and modify the variables visible in its lexical scope, even after the outer function has returned:

Go
func counter() func() int {
    n := 0
    return func() int {
        n++
        return n
    }
}

c := counter()
fmt.Println(c(), c(), c())  // 1 2 3

n "lives" as long as at least one closure references it. Each call to counter() creates a new, independent n.

Closure as callback

A very common pattern:

Go
nums := []int{3, 1, 2}
sort.Slice(nums, func(i, j int) bool {
    return nums[i] < nums[j]
})

The closure captures nums and defines the ordering.

Functions as parameters

To accept a function as a parameter, write out its type:

Go
func apply(nums []int, f func(int) int) []int {
    out := make([]int, len(nums))
    for i, n := range nums {
        out[i] = f(n)
    }
    return out
}

double := func(x int) int { return x * 2 }
apply([]int{1, 2, 3}, double)   // [2 4 6]

If the signature becomes hard to read, define a type alias:

Go
type Transform func(int) int
func apply(nums []int, f Transform) []int { ... }

Try it

锻炼#go.m3.l4.e1
尝试:0加载中...

Define counter() that returns a closure: each call to the closure increments and returns an internal counter.

正在加载编辑器...
显示提示

`n` must be declared BEFORE the return; the closure captures it.

3 次尝试后可用的解决方案

锻炼#go.m3.l4.e2
尝试:0加载中...

Assign to f a function literal that prints 'ciao', then call it.

正在加载编辑器...
显示提示

Syntax: `f := func() { ... }` then `f()`.

3 次尝试后可用的解决方案

Quiz#go.m3.l4.e3
准备好

What does this print? (watch out for closure scope)

Go
mk := func() func() int {
    x := 0
    return func() int { x++; return x }
}
a := mk()
b := mk()
fmt.Println(a(), a(), b())
答案选项

Recap

  • Functions are first-class: assignable, passable, returnable.
  • Function literal: func(params) ret { ... }, anonymous.
  • Closure: captures the variables of the lexical scope, keeps them alive.
  • Explicit function type in parameters: func(int) int.
  • Since Go 1.22, every for iteration has its own copy of the loop variable.