07-函式‎ > ‎

07.04-Closure

Closure

可以在函式中建立函式:

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

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

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 的一種使用方式是,透過設計一個函式,此函式會傳回另一個函式的結果(被呼叫時可以產生一串號碼),例如,下列會產生全部的偶數:

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,與一般區域變數的差異是:此變數存在於兩個呼叫之間。

Comments