6.1.錯誤
Go語言中使用builtin包下error接口作為錯誤類型
Go語言中錯誤都作為方法/函數的傳回值
自定義錯誤類型
//Learn_Go/main.go
package main
import (
"errors"
"fmt"
)
func demo(i,k int) (r int, e error) {
if k == 0 {
e = errors.New("除數不能為0")
return
}
r = i/k
return
}
func main() {
//result,error := demo(6,3)
result,e := demo(6,0)
if e != nil{
fmt.Println("執行錯誤,錯誤資訊為:",e) //執行錯誤,錯誤資訊為: 除數不能為0
return
}
fmt.Println("執行成功,結果:",result) //執行成功,結果: 2
}
複制
6.2.defer
Go語言中defer可以完成延遲功能,目前函數執行完成後執行defer功能
defer最常用的就是關閉連接配接(資料庫,檔案等),可以打開連接配接後緊跟defer進行關閉
(1)Go語言中defer無論寫到哪裡都是最後執行,不用非要把關閉代碼寫在最後
//Learn_Go/main.go
package main
import "fmt"
func main() {
fmt.Println("打開連接配接")
//defer fmt.Println("關閉連接配接")
defer func() {
fmt.Println("關閉連接配接") //defer執行
}()
fmt.Println("進行操作")
}
//結果
打開連接配接
進行操作
關閉連接配接
複制
(2)多個defer
多重defer采用棧結構執行,先産生後執行
在很多代碼結構中都可能出現産生多個對象,而程式希望這些對象倒叙關閉,多個defer正好可以解決這個問題
//Learn_Go/main.go
package main
import "fmt"
func main() {
fmt.Println("打開連接配接A")
defer fmt.Println("關閉連接配接A")
fmt.Println("打開連接配接B")
defer fmt.Println("關閉連接配接B")
fmt.Println("打開連接配接C")
defer fmt.Println("關閉連接配接C")
fmt.Println("進行操作")
}
//結果
打開連接配接A
打開連接配接B
打開連接配接C
進行操作
關閉連接配接C
關閉連接配接B
關閉連接配接A
複制
(3)defer和return結合
defer與return同時存在時,要把return了解成兩條執行結合,一個指令是給傳回值
指派,另一個指令傳回跳出函數
defer和return時整體執行順序
- 先給傳回值指派
- 執行defer
- 傳回跳出函數
(4)沒有定義傳回值接收變量,執行defer時傳回值已經指派
//Learn_Go/main.go
package main
import "fmt"
func demo() int {
i := 1
defer func() {
i = i + 2
}()
return i
}
func main() {
fmt.Println(demo()) //1
}
複制
(5)聲明接收傳回值變量,執行defer時修改了傳回值内容
//Learn_Go/main.go
package main
import "fmt"
func demo() (z int) {
i := 1
defer func() {
z = i + 2
}()
return
}
func main() {
fmt.Println(demo()) //3
}
複制
6.3.panic
panic是build中函數,當執行到panic後,終止剩餘代碼執行,并列印錯誤棧資訊。
//Learn_Go/main.go
package main
import "fmt"
func main() {
fmt.Println("111")
panic("錯誤資訊")
fmt.Println("222")
}
//結果
111
panic: 錯誤資訊
goroutine 1 [running]:
main.main()
C:/Users/86158/Desktop/Learn_Go/main.go:8 +0x82
複制
panic不是立即停止程式,defer還是執行的
//Learn_Go/main.go
package main
import "fmt"
func main() {
defer fmt.Println("執行defer的内容")
fmt.Println("111")
panic("錯誤資訊")
fmt.Println("222")
}
//結果
111
執行defer的内容
panic: 錯誤資訊
goroutine 1 [running]:
main.main()
C:/Users/86158/Desktop/Learn_Go/main.go:9 +0xdc
複制
6.4.recover
recover()表示回複程式的panic(),讓程式正常執行
rcover()是和panic一樣都是builtin中函數,可以接受panic的資訊,恢複程式的正常執行
recover()一般在defer内部,如果沒有panic資訊,傳回nil;如果有panic,recover會把panic狀态取消
//Learn_Go/main.go
package main
import "fmt"
func main() {
defer func() {
if error := recover();error != nil{
fmt.Println("panic為:", error)
}
}()
fmt.Println("111")
panic("出現了錯誤資訊")
fmt.Println("222")
}
//結果
111
panic為: 出現了錯誤資訊
複制
函數調用過程中panic和recover()
- recover()隻能恢複目前函數級或目前函數調用函數中的panic(),恢複後調用目前級别函數結束,但是調用此函數的函數可以繼續執行
- panic會一直向上傳遞,如果沒有recover()則表示程式終止,但是碰見了recover(),recover()所在級别函數表示沒有panic,panic就不會向上傳遞
//Learn_Go/main.go
package main
import "fmt"
func demo1() {
fmt.Println("demo1上半部分")
demo2()
fmt.Println("demo1下半部分")
}
func demo2() {
fmt.Println("demo2上半部分")
demo3()
fmt.Println("demo2下半部分")
}
func demo3() {
fmt.Println("demo3上半部分")
panic("demo3中出現panic")
fmt.Println("demo3下半部分")
}
func main() {
fmt.Println("程式開始")
demo1()
fmt.Println("程式結束")
}
//結果
程式開始
demo1上半部分
demo2上半部分
demo3上半部分
panic: demo3中出現panic
複制
demo3添加recover()
//Learn_Go/main.go
package main
import "fmt"
func demo1() {
fmt.Println("demo1上半部分")
demo2()
fmt.Println("demo1下半部分")
}
func demo2() {
fmt.Println("demo2上半部分")
demo3()
fmt.Println("demo2下半部分")
}
func demo3() {
defer func() {
recover()
}()
fmt.Println("demo3上半部分")
panic("demo3中出現panic")
fmt.Println("demo3下半部分")
}
func main() {
fmt.Println("程式開始")
demo1()
fmt.Println("程式結束")
}
//結果
程式開始
demo1上半部分
demo2上半部分
demo3上半部分
demo2下半部分
demo1下半部分
程式結束
複制
demo2添加recover()
//Learn_Go/main.go
package main
import "fmt"
func demo1() {
fmt.Println("demo1上半部分")
demo2()
fmt.Println("demo1下半部分")
}
func demo2() {
defer func() {
recover()
}()
fmt.Println("demo2上半部分")
demo3()
fmt.Println("demo2下半部分")
}
func demo3() {
fmt.Println("demo3上半部分")
panic("demo3中出現panic")
fmt.Println("demo3下半部分")
}
func main() {
fmt.Println("程式開始")
demo1()
fmt.Println("程式結束")
}
//結果
程式開始
demo1上半部分
demo2上半部分
demo3上半部分
demo1下半部分
程式結束
複制