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())
}
Tags: