Go語言學習——函數二 defer語句
函數
package main
import "fmt"
// 函數:一段程式碼的封裝
func f1(){
fmt.Println("Hello 中國!")
}
func f2(name string) {
fmt.Println("Hello", name)
}
// 帶參數和返回值的函數
func f3(x int, y int) int {
sum := x + y
return sum
}
// 參數類型簡寫
func f4(x, y int) int {
return x + y
}
// 可變參數
func f5(title string, y ...int) int {
fmt.Println(y) // y是一個int類型的切片
return 1
}
// 命名返回值
func f6(x, y int) (sum int) {
sum = x + y // 如果使用命名的返回值,那麼在函數中可以直接使用返回值變數
return // 如果使用命名的返回值 return 後面可以省略返回值變數
}
// Go語言中支援多個返回值
func f7(x, y int) (sum, sub int) {
sum = x + y
sub = x - y
return
}
func main () {
f1()
f2("理想")
f2("夢想")
f3(100, 200) // 調用函數
fmt.Println(f3(100, 200))
ret := f3(300, 400)
fmt.Println(ret)
f5("太陽", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 在一個命名的函數中不能夠再聲明命名函數
// func f8() {
// }
}
defer語句
defer語句會將其後面跟隨的語句進行延遲處理
在defer歸屬的函數即將返回時,將延遲處理的語句按defer定義的逆序進行執行
先被defer的語句最後被執行,最後被defer的語句,最先被執行
package main
import "fmt"
// defer
// defer多用於函數結束之前釋放資源(文件句柄、資料庫連接、socket連接)
func deferDemo(){
fmt.Println("start")
defer fmt.Println("hello") // defer把它後面的語句延遲到函數即將返回的時候再執行
defer fmt.Println("apple") // 一個函數中可以有多個defer語句
defer fmt.Println("banana") // 多個defer語句安裝先進後出(後進先出)的順序延遲執行
fmt.Println("end")
}
func main(){
deferDemo()
}
defer執行時機
return語句在底層並不是原子操作,它分為給返回值賦值和RET指令兩步
defer語句執行的時機在返回值賦值操作後,RET指令執行前
package main
import "fmt"
// Go語言中函數的return不是原子操作,在底層分為兩步來執行
// 第一步:返回值賦值
// defer
// 第二版:真正的RET返回
// 函數中如果存在defer,那麼defer執行的時機是在第一步和第二步之間
func f1() int {
x := 5
defer func() {
x++ // 修改的是x不是返回值
}()
return x
}
func f2() (x int) {
defer func() {
x++
}()
return 5 // 返回值=x
}
func f3() (y int) {
x := 5
defer func() {
x++ // 修改的是x
}()
return x // 返回值=y=x=5
}
func f4() (x int) {
defer func(x int) {
x++ // 改變的是函數中的副本
}(x)
return 5 // 返回值=x=5
}
func main() {
fmt.Println(f1())
fmt.Println(f2())
fmt.Println(f3())
fmt.Println(f4())
}