上一篇我們已經知道go語言的map
今天介紹函數,defer,函數類型
函數
在我們前面關於go的所有文章中 很經常看到 func main()
的內容
這個就是主函數 這個函數有個特點 就是不會有返回值 不會有參數
可以看到 函數的關鍵字就是func
在定義函數過程中 如果有定義返回類型的 就必須要return
換言之,有retrun
就必須聲明返回值的類型(多個返回值 就需要用括號包裹起來)
並且 go語言中 函數的參數 是沒有默認值的
語法:
//返回值可以命名 也可以不命名 同樣 參數也可以
func 函數名(參數 參數類型)(返回值 返回值類型){}
//匿名函數
func(形參){}(實參)
示例:
注意 函數的調用 必須在main
函數中才可以調用
package main
import "fmt"
//定義一個 求合函數
func add(a int,b int)(c int){
return a + b
}
func main(){
//調用求合函數
res := add(1,2)
fmt.Println(res)
//匿名函數
func(x,y int){
fmt.Println(x,y)
}(1,2)
}
函數的定義有着多種寫法 這邊簡單概括一下:
沒有參數的 沒有返回值的
func f1(){
fmt.Println("這是f1函數 調用我 我就輸出")
}
//在main函數中調用的寫法
f1()
沒有參數 有返回值的
func f2()string{
return "f2"
}
//在main函數中調用的寫法
f2 := f2()
fmt.Println(f2)
有命名參數 有命名返回值
func f3(x int , y int)(ret int){
return x + y
//這裏不需要在通過ret進行接收
}
//在main函數中調用的寫法
f3:= f3(2,3)
fmt.Println(f3)
多個返回值
func f4()(int,string){
return 1,"zzs"
}
//在main函數中調用的寫法 需要多個值接收
f41,f42:= f4()
fmt.Println(f41,f42)
參數類型相同的情況下簡寫
func f5(x,y int){
return x-y
}
//在main函數中調用的寫法
f5:= f5(8,6)
fmt.Println(f5)
可變長參數
也就是可以傳多個但是其實就是一個切片
這個參數 只能做爲最後一個參數
func f6(x string,y ...int){
fmt.Println(x)
fmt.Println(y)
}
//在main函數中調用的寫法
f6("zzs",1,2,3,4,4,56,7)
新建一個文件夾func
文件夾下新建main.go
調用上述的各種函數 查看效果吧
package main
import "fmt"
func f1(){
fmt.Println("這是f1函數 調用我 我就輸出")
}
func f2()string{
return "f2"
}
func f3(x int , y int)(ret int){
return x + y
//這裏不需要在通過ret進行接收
}
func f4()(int,string){
return 1,"zzs"
}
func f5(x,y int)int{
return x-y
}
func f6(x string,y ...int){
fmt.Println(x)
fmt.Println(y)
}
func main(){
f1()
f2 := f2()
fmt.Println(f2)
f3:= f3(2,3)
fmt.Println(f3)
f41,f42:= f4()
fmt.Println(f41,f42)
f5:= f5(8,6)
fmt.Println(f5)
f6("zzs",1,2,3,4,4,56,7)
}
defer
defer
就是 把後面的語句延遲執行 延遲到函數即將返回的時候執行
所以 defer只能用於函數中
多用於處理資源的釋放 文件句柄 數據庫連接 socket連接
如果有多個defer 那麼越上面的defer的語句越晚執行
關於上述的函數即將返回的時候
這個描述
如何理解?
要知道 在go語言中 return不是原子操作 屬於非原子操作
所謂的原子操作就是 一步到位 非原子操作是多步
所以go的return
分爲兩位:
- 返回值賦值
- 值進行返回
因此,如果存在defer
,那就是在上述的兩步之間執行!
示例:
func main(){
fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
fmt.Println(4)
}
//代碼通常都是 從上執行到下 加上defer之後 可以看到結果:1 4 3 2 這就是defer的使用
單看上述的例子 可能還無法理解
加深defer的印象
新建文件夾defer 文件夾下新建文件 main.go
package main
import "fmt"
//場景1
func demo1()int{
x := 5
//匿名函數
defer func(x int){
x++
}(x)
return x
}
//場景2
func demo2()(x int){
defer func(){
x++
}()
return 5
}
//場景3
func demo3()(y int){
x:=5
defer func(){
x++
}()
return x
}
//場景4
func demo4()(x int){
defer func(x int){
x++
}(x)
return 5
}
func main(){
fmt.Println(demo1()) //5 此時修改的是 x 而返回值5已經賦值給x了 所以結果是 5
fmt.Println(demo2()) //6 返回之前進行賦值
fmt.Println(demo3()) //5 x賦值給5 x是5 所以是 y 5
fmt.Println(demo4()) //5 運算後賦值 所以是
}
函數類型
爲什麼要了解函數的類型呢 因爲函數也可以當作參數 所以需要寫對正確的函數結構體才能實現程序的運行
函數類型可以通過 fmt
包的Printf("%T \n",要輸出的對象)
下面我將通過例子 將各種形式的函數 打印出他們的類型:
新建文件夾func_type 文件夾下新建main。
package main
import "fmt"
func f1(){
fmt.Println("f1")
}
func f2()int{
return 2
}
func f3(f func() int){
ret := f()
fmt.Println(ret)
}
func f4(x,y int)int{
return x+y
}
func f5(x func() int)func(int,int)int{
return func(a,b int)int{
return a+b
}
}
func main(){
fmt.Printf("%T \n",f1)//func()
fmt.Printf("%T \n",f2)//func() int
//調用f3
f3(f2)
fmt.Printf("%T \n",f3)//func(func() int)
fmt.Printf("%T \n",f4)//func(int,int) int
fmt.Printf("%T \n",f5)//func(func() int)func(int,int)int
}
關於函數的介紹就先到這裏 很重要的一個知識點!
有問題歡迎在評論區留言
未完待續。。。