上一篇我們已經知道go語言的函數,defer,函數類型
今天介紹閉包
閉包是什麼?
閉包就是 函數和它的外部變量的引用
可以說 閉包也是一個函數 它的特點是 包含了外部作用域的一個變量
底層原理
函數作爲返回值
函數內部查找變量的順序:先在內部查找,找不到再到外部查找
基本用法
package main
import "fmt"
//demo1
func f1(f func()){
fmt.Println("f1")
f()
}
//demo2
func f2(x,y int){
fmt.Println("f2")
fmt.Println(x+y)
}
//可以看到 f1函數所能接收的參數類型是 沒有帶參數的函數 很顯然 f2 是不符合當參數傳進去的
//那麼 如何把f2 變成符合條件的函數呢?
func f3(x,y int)func(){
return func(){
f2(x,y)
}
}
//通過上述f3的處理 將f2 轉換成 符合f1條件的函數形式 進行傳入
//但是上述的方法存在侷限性 畢竟是 針對於f2函數的 那麼如何設計成 只要是f2這種類型的函數 都能適用呢
//參數分別是 兩個參數都是int的函數,還有這個函數對應的兩個形參
func f4(f func(int,int),x ,y int)func(){
return func(){
f(x,y)
}
}
func main(){
//驗證f3
f1(f3(1,2))
//可以看到 輸出結果是 f1 f2 3 這就是閉包的應用
//驗證f4
f1(f4(f2,2,3))
//很顯然 結果是 f1 f2 5 這樣 以後凡是f2這種類型的函數 都可以通過f4進行處理
}
示例
示例1:定義一個函數 返回一個函數 這個函數接收一個int參數 並且返回一個int結果
package main
import "fmt"
func addr()func(int)int{
var x int = 100
return func(y int)int{
x += y
return x
}
}
//改寫上述的方法 比較 具有可讀性
func addr2(x int)func(int)int{
return func(y int)int{
return x+y
}
}
func main(){
//如何使用addr函數?
//首先調用addr函數
ad := addr()
//此時ad是一個 接收一個int參數 並且返回一個int結果 的函數
res := ad(100)
//此時100進去之後 按照閉包的原理 先在函數內部查找參數 找到了 是y 所以 100賦值給Y 之後和x進行運算 結果 200
fmt.Println(res)
//如果以上的調用過程覺得繁瑣 直接一步到位!
fmt.Println(addr()(100))
//驗證改寫後的函數
//首先還是調用
ad2 := addr2(100)
res2 := ad2(100)
fmt.Println(res2)
//如果以上的調用過程覺得繁瑣 直接一步到位!
fmt.Println(addr2(100)(100))
}
示例1:創建一個閉包 如果 傳入的第一次參數內容和第二參數以後 如果前面的內容是在後面內容的後綴 那麼就照常返回 否則就返回拼接兩次參數內容的結果這裏判斷後綴 會引入 strings包
比如 第一次傳的是 .gif
第二次傳的是 zzs.gif
那麼第一次是屬於第二次的後綴 那麼就返回第二次傳參的內容
再比如 第一次傳的是.gif
第二次傳的是 zzs
那麼第一次不屬於第二次的後綴 那麼就返回兩次拼接的結果
package main
import (
"fmt"
"strings"
)
func name(first string)func(string)string{
return func(second string)string{
//如果 第一次的參數 不存在於第二參數的後綴上 那麼就拼接兩次傳入的內容
if !strings.HasSuffix(second,first) {
return first + second
}
//否則就返回第二次的內容
return second
}
}
func main(){
//如何調用呢?
first := name("jpg")
second := first("zzs.jpg")
fmt.Println(second)
first2 := name(".gif")
second2 := first2("zzs")
fmt.Println(second2)
//一步到位
fmt.Println(name(".gif")("zzs"))
}
示例3:定義一個函數 返回兩個函數 這兩個函數 一個是加法函數 一個是減法函數
package main
import "fmt"
func calc()(func(int ,int)int,func(int ,int)int){
add := func(x ,y int)int{
x += y
return x
}
sub := func(x ,y int)int{
x -= y
return x
}
return add,sub
}
func main(){
//定義兩個變量 接收calc函數的兩個返回結果
add,sub := calc()
fmt.Println(add(100,50))
fmt.Println(sub(100,50))
}
閉包的介紹就到這裏
個人覺得 是非常有意思的的知識點 寫起來就停不下來的感覺
歡迎在評論區進行留言
未完待續。。。