> For the complete documentation index, see [llms.txt](https://go.netdpi.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://go.netdpi.net/functions/07.04-closure.md).

# 07.04-Closure

可以在函式中建立函式：

```go
func main() {
    add := func(x, y int) int {
        return x + y
    }
    fmt.Println(add(1,1))    
}
```

`add` 是一個區域變數，型別是 `func(int, int) int`（一個需要帶入兩個 `int` 型別以及傳回一個 `int` 型別的函式）當我們建立一個區域函式時，此函式只能存取其它區域變數（如第四章的 scope 所述）。

```go
func main() {
    x := 0
    increment := func() int {
        x++
        return x
    }
    fmt.Println(increment())
    fmt.Println(increment())    
}
```

`increment` 將 1 加到 `x` 變數，此變數定義於 `main` 函式的 scope，increment 函式可以存取與修改 `x` 變數，這就是為何我們在第一次呼叫 `increment` 時會看到顯示為 1，而第二次會看到顯示 2。

類似的函式與函式所參照的非區域變數合稱為所謂的 closure，以同樣的例子， `increment` 與  `x` 變數形成了一個 closure。

Closure 的一種使用方式是，透過設計一個函式，此函式會傳回另一個函式的結果（被呼叫時可以產生一串號碼），例如，下列會產生全部的偶數：

```go
func makeEvenGenerator() func() uint {
    i := uint(0)
    return func() (ret uint) {
        ret = i
        i += 2
        return
    }
}
func main() {
    nextEven := makeEvenGenerator()
    fmt.Println(nextEven()) // 0
    fmt.Println(nextEven()) // 2
    fmt.Println(nextEven()) // 4
}
```

`makeEvenGenerator` 會傳回一個函式（此函式會產生偶數），每次呼叫此函式時，它會將 2 加到區域變數 `i`，與一般區域變數的差異是：此變數存在於兩個呼叫之間。
