函數的數據類型
Go語言中的函數可以作爲一種複合的數據類型。
package main
import "fmt"
func fun1(a, b int) {
fmt.Println("a:", a, ",b:", b)
}
func fun2(a, b int) int {
return a + b
}
func main() {
// 函數作爲一個變量
fmt.Printf("%T:\t", fun1)
fmt.Println(fun1) //func(int, int): 0x498450
// 直接定義一個函數類型的變量
var c func(int, int)
fmt.Printf("%T:\t", c)
fmt.Println(c) // func(int, int): <nil>
c = fun1; //將fun1的值(函數體的地址),賦值給c
fmt.Println(c) //0x498450
fun1(10, 20) // 調用函數 a: 10 ,b: 20
c(100, 200) // 調用函數 a: 100 ,b: 200
res1 := fun2 //將fun2的值(函數的地址),賦值給res1,res1和fun2指向同一個函數體
res2 := fun2(1, 2)//將fun2函數進行調用,將函數的執行結果,賦值給res2,相當於:res = a+b
fmt.Println(res2) // 3
fmt.Println(res1) //0x498590
fmt.Println(res1(10,20)) //30
}
函數的本質
package main
import "fmt"
func main() {
/*
函數作爲一種複合的數據類型,可以將函數也看做是一種變量。
*/
//1.作爲一個int類型的變量的常規操作
var num1 int
num1 = 100
fmt.Println(num1) //100
//2.將一個函數看成一個變量的操作
fmt.Printf("%T\n",fun1) // func(int,int)int
var a func(int,int)int
a = fun1 // 將fun1賦值給a
fmt.Printf("%T\n",a)
r1:=a(1,2) //a作爲一個函數的變量,可以直接被調用
fmt.Println(r1) // 3
r2:=fun1(10,20)
fmt.Println(r2)
b := fun1 //將fun1直接賦值給b,那麼b是func函數,
c := fun1(100,200)//將fun1的執行結果賦值給c,int類型的數據
b(1,2)
//c()
fmt.Println(c)
fmt.Printf("%v\n",fun1)
fmt.Printf("%v\n",a)
fmt.Printf("%v\n",b)
}
func fun1(a, b int) int{ // func(int,int)int
return a + b
}
匿名函數
匿名函數,就是沒有名字的函數。
定義一個匿名函數,直接進行調用。通常只能使用一次。也可以將匿名函數賦值給某個函數變量。那麼可以調用多次。
匿名函數:
1.將函數作爲另一個函數的參數。回調函數
2.將函數作爲另一個函數的返回值。
package main
import "fmt"
func fun1(){
fmt.Println("我是fun1函數。。")
}
func main() {
fun1()//調用函數
fun2:=fun1
fun2()//調用函數
//匿名函數:
func (){
fmt.Println("我是一個匿名函數。。")
}()
fun3:=func(){
fmt.Println("我也是一個匿名函數。。")
}
fun3()
fun3()
//定義帶參數的匿名函數
func(a, b int){
fmt.Println(a, b)
}(1,2)
//定義帶返回值的函數
res1:=func(a, b int)int{
return a + b
}(10,20) //匿名函數調用了,將調用執行的結果給res1
fmt.Println(res1)
res2 :=func(a,b int)int{
return a+b
}//將匿名函數的值,賦值給res2
fmt.Println(res2) // 0x496910
}
回調函數
高階函數:
根據go語言的數據類型的特點,可以將一個函數作爲另一個函數的參數。
fun1(),fun2()
將fun1函數作爲了fun2這個函數的參數。
fun2函數:就叫高階函數
接收了一個函數作爲參數的函數,高階函數
fun1函數:回調函數
作爲另一個函數的參數的函數,叫做回調函數。
package main
import "fmt"
//加法運算
func add(a, b int) int{
return a + b
}
func sub(a, b int)int{
return a-b
}
func oper(a, b int,fun func (int,int)int) int{
fmt.Println(a,b,fun)//打印3個參數
res := fun(a, b)
return res
}
func main() {
fmt.Printf("%T\n",add) //func(int, int) int
fmt.Printf("%T\n",oper) //func(int, int, func(int, int) int) int
res1 := add(1,2)
fmt.Println(res1)
res2 := oper(10,20,add)
fmt.Println(res2)
res3:=oper(5,2,sub)
fmt.Println(res3)
fun1:=func (a, b int)int{
return a * b
}
res4:=oper(10,4,fun1)
fmt.Println(res4)
res5:=oper(100,8, func(a int, b int) int {
if b == 0 {
fmt.Println("除數不能爲令")
return 0
}
return a / b
})
fmt.Println(res5)
}
閉包
go語言支持函數式編程
支持將一個函數作爲另一個函數的參數
也支持將一個函數作爲另一個函數的返回值。
閉包(closure):
一個外層函數中,有內層函數,該內層函數中,會操作外層函數中的局部變量(外層函數中的參數,或者外層函數直接定義的變量),並且該外層函數的返回值就是這個內存函數。
局部變量的生命週期會發生改變,正常的局部變量隨着函數的調用而創建,隨着函數的結束而銷燬。
但是閉包結構中的外層函數的局部變量並不會隨着外層函數的結束而銷燬,因爲內層函數還要繼續使用。
package main
import "fmt"
//可以將一個函數作爲返回值。
func increment() func()int{//外層函數
//1.定義了一個局部變量
i := 0
//2.定義了一個匿名函數,給變量自贈了並返回
fun := func ()int{//內層函數
i++
return i
}
//3.返回該匿名函數
return fun
}
func main() {
res1:=increment() //res1 = fun
fmt.Printf("%T\n",res1) //func() int
fmt.Println(res1) //0x498570
v1:=res1()
fmt.Println(v1)//1
v2 :=res1()
fmt.Println(v2)//2
fmt.Println(res1())//3
fmt.Println(res1())//4
fmt.Println(res1())//5
fmt.Println(res1())//6
res2:=increment()
v3:=res2()
fmt.Println(v3) //1
v4:=res2()//2
fmt.Println(v4)
v5 := res1()
fmt.Println(v5)//7
}