Hike News
Hike News

Go初識-day10-閉包(closure)

introduction

閉包可以用來在一個函式與一組「私有」變數之間建立關聯關係。在給定函式被多次呼叫的過程中,這些私有變數能夠保持其永續性。變數的作用域僅限於包含它們的函式,因此無法從其它程式代碼部分進行存取。不過,變數的生存期是可以很長,在一次函式呼叫期間所建立所生成的值在下次函式呼叫時仍然存在

  • 一個函數和與其相關的引用環境組合而成的實體

example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import "fmt"

func SaveAdd() func(int) int { //[1]
var x int
return func(add int) int { //[2]
x += add
return x
}
}

func main(){
f := SaveAdd() //[3]
fmt.Println(f(1)) //[4]
fmt.Println(f(100))
fmt.Println(f(1000))
}

[1] SaveAdd函數的返回值為一個函數
[2] return的匿名函數引用了函數外的變量x,使得return的這個匿名函數成為了閉包,而被綁定的x變量會記得被調用的狀態,等待下次再被調用
[3] f為一個被已執行函數賦值的變量
[4] f的參數為[2]return匿名函數的參數

result

1
2
3
1
101
1101

f一直存在,其中的x變量指向的值仍為同一塊內存空間,故保留了函數return匿名函數對x的操作並返回x之值


換句話說 (python)

可將整個函數當成一個class,對class內部的函數來說
外部變量就相當於class屬性
內部的函數操作類屬性時,類屬性會改變,且會記住被操作的最後狀態,並等待下次被其他內部函數操作

1
2
3
4
5
6
7
8
9
10
11
12
class outerFunction():
def __init__(self):
self.outervar = 1

def inner_function(self,var):
self.outervar += var

if __name__ == "__main__":
f = outerFunction()
print("outervar =",f.outervar)
f.inner_function(2)
print("outervar =",f.outervar)

result

1
2
1
3

f物件並未消失,所以類屬性內部類函數操作時,仍會記住其屬性狀態


檢測文件後綴名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main

import (
"strings"
"fmt"
)

func detect_extension(extension string) func(string string) string {
return func(filename string) string {
if strings.HasSuffix(filename,extension) == false { //[1]
return filename + extension
}
return filename
}
}

func main(){
bmp := detect_extension(".bmp") //[2]
jpg := detect_extension(".jpg")

fmt.Println(bmp("test")) //[3]
fmt.Println(bmp("test_2.bmp"))
fmt.Println(jpg("TEST"))
fmt.Println(jpg("TEST_2.jpg"))

}

[1] 內部匿名函數引用了外部的變量extension
[2] 調用函數並綁定了extension變量
[3] 對內部的匿名函數傳參

result

1
2
3
4
test.bmp
test_2.bmp
TEST.jpg
TEST_2.jpg

Reference

https://zh.wikipedia.org/wiki/%E9%97%AD%E5%8C%85_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)