Go基礎知識複習之閉包

上一篇我們已經知道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))
}

閉包的介紹就到這裏
個人覺得 是非常有意思的的知識點 寫起來就停不下來的感覺
歡迎在評論區進行留言
未完待續。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章