1. 程式人生 > 其它 >Go xmas2020 全英課程 08 學習筆記、Functions, Parameters & Defer

Go xmas2020 全英課程 08 學習筆記、Functions, Parameters & Defer

課程地址 go-class-slides/xmas-2020 at trunk · matt4biz/go-class-slides (github.com)

主講老師 Matt Holiday

08-Functions, Parameters

functions

first class

你可以在函式體內宣告函式,但必須是匿名函式,作為一個變數


function signatures

函式簽名指的是 函式引數型別與排列順序、函式返回值


parameter

pass by value

func do(b [3]int) int {
	b[0] = 0
	return b[1]
}

func main() {
	a := [3]int{1, 2, 3}
	v := do(a) // ^ 陣列被複制到函式的區域性變數
	fmt.Println(a, v)
}
[1 2 3] 2

pass by reference

func do(b []int) int {
	b[0] = 0
	fmt.Printf("b2 @ %p\n", b)
	b = append(b, 100)
	b = append(b, 100)
	fmt.Printf("b3 @ %p\n", b)
	return b[1]
}

func main() {
	a := []int{1, 2, 3}
	fmt.Printf("b1 @ %p\n", a)
	v := do(a) // ^ 切片被複制到函式的區域性變數
	fmt.Println(a, v)
}
b1 @ 0xc00012c078
b2 @ 0xc00012c078
b3 @ 0xc00013e060
[0 2 3] 2

func do(m1 map[int]int) {
	m1[3] = 0              // ^ 兩個描述符和相同的雜湊表,且雜湊表有三個鍵,因此修改m1,m被修改
	m1 = make(map[int]int) // ^ 分配了新對映,但m不會被改變
	m1[4] = 4
	fmt.Println("m1", m1)
}

func main() {
	m := map[int]int{4: 1, 7: 2, 8: 3}
	do(m)
	fmt.Println(m)
}
m1 map[4:4]
map[3:0 4:1 7:2 8:3]

the ultimate truth

go 裡只有值傳遞,函式內的變數都是區域性變數,它被分配、拷貝實際引數的值,假如傳入的是切片描述符,它也是被複制到區域性變數裡的。描述符被複制,切片底層資料沒有被複制。


returns


Recursion

遞迴執行比迭代慢因為要建立一系列堆疊幀。


08-Defer

defer gotcha #1

Defer is based on function scope

第二個例子中,只有退出函式才會執行 defer 將會開啟很多檔案導致程式崩潰。所以直接使用 f.close 關閉檔案。


defer gotcha #2

defer 執行時,以引數實際的值拷貝傳遞進延遲函式並壓入 defer棧 中,而不是引用。


當我離開函式時執行延遲堆疊,延遲的匿名函式修改返回值 a