08-Functions, Parameters、 functions、 first class、 function signatures、 parameter、 pass by value、 p... ...
課程地址 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