第五章 函数
< P120 >
函数传参都是值传递;在传递
slice
时,会复制一个slice
的struct
,包含了底层数组指针、len
、cap
,虽然被调用函数可以改变底层数组,但是其中len
,cap
等对调用者是不可见的,除非用指针或返回新值更新;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20func f1(val []int) {
val = append(val, 123)
}
func f2(val []int) []int {
val = append(val, 321)
fmt.Println(len(val))
return val
}
func main() {
var val = make([]int, 0, 10)
f1(val)
val = f2(val)
for i, v := range val {
fmt.Printf("%d\t%d\n", i, v)
}
}
// 1
// 0 321函数的类型又称作函数签名(signature),参数以及返回值的变量名对签名无影响;
- Go的栈是可变的,取决于内存大小, 可以增长到数G;
< P125 >
- go的GC不会回收操作系统资源,如打开的文件、网络连接等,必须进行显式的回收;
- 当所有返回值都是具名的,return的操作数可以忽略,称作裸返回(bare return);
< P134 >
- 函数可以赋值,即函数可以作为参数传递;
%*s
中的*
修饰符可以指定字符串前有多少空格;1
fmt.Printf("%*s", 5 , "text")
< P135 >
具名函数只能在包级定义;但是匿名函数可以在函数内部给函数变量赋值;但是如果需要递归调用,用:=
定义函数变量会导致不能调用自身,可以尝试下面这种方式:
1 | var visitAll func(items []string) |
< P141 >
注意在使用闭包时捕获迭代局部变量的问题,应该用一个新的局部变量保存;
< P144 >
- 在运行到
defer
语句时,deferred的函数参数值就确定了,只有函数的执行被延迟; - Deferred的函数在
return
之后执行;
< P151 >
Deferred的函数调用的runtime.Stack
方法可以打印panic
时的stack
是因为Go的panic
机制会先运行deferred function再unwind the stack;