函数传递机制
func add(a int) int { a++ return a } func addo(a *int) int { *a++ return *a } func main() { x := 3 fmt.Println("x=", x, " &x=", &x) y := add(x) //执行add实际上修改的是x的副本 fmt.Println("x=", x, " y=", y) //输出的还是x原来的值,改变的是副本y z := addo(&x) //执行addo函数,实际上修改的是x的值 fmt.Println("x=", x, " z=", z) //输出的x已经被修改 fmt.Println("&x=", &x) //x的地址还是原来的 } 结果: x= 3 &x= 0xc0000140a8 x= 3 y= 4 x= 4 z= 4 &x= 0xc0000140a8
传指针最明显的三点好处:
1.传指针使得多个函数能操作同一个对象
2.传指针比较轻量级(8B),毕竟只传递内存地址,可以用指针传递体积大的结构体。如果传递值,在每次创建副本上面就会花费相对较多的系统开销(内存和时间),所以当传递较大的结构体时候,用指针是一个明智的选择。
3.传递指针给函数不但可以节省内存(因为没有复制变量的值),而且赋予了函数直接修改外部变量的能力,所以被修改的变量不在需要使用 return 返回。
func main() { n := 0 res := &n muliply(2, 4, res) fmt.Println("Result:", *res) fmt.Println("n的地址:", &n) fmt.Println("n的值:", n) fmt.Println("res直接打印:", res) fmt.Println("res的地址:", &res) } func muliply(a, b int, res *int) { *res = a * b }
res是一个指向int变量的指针,通过这个指针,在函数内修改了这个int变量的值。
defer与跟踪
defer延迟语句可以在函数中添加多个,当函数执行到最后(return语句执行之前),这些defer语句会按照后进先出的顺序执行(类似栈,先进后出)。
举个方便的小例子:
func ReadWrite()bool{ file.Open("file") defer file.Close() //文件打开和关闭都放在一起写不容易遗漏。其他语言可能得写两句,而且关闭是之后的操作,可能造成遗忘出错 }
先进后出类似栈的进出
func main() { for i:=0;i<5;i++{ defer fmt.Println(i) } } 结果: 4 3 2 1 0
关于defer,return和返回值之间的执行顺序
1.函数值被命名
func a() int { var i = 1 defer func() { i++ fmt.Println("defer2:", i) }() defer func() { i++ fmt.Println("defer1:", i) }() return i } 结果: defer1: 2 defer2: 3 return: 1
2.有命名返回值情况下
func main() { fmt.Println("return:", b()) } func b() (i int) { defer func() { i++ fmt.Println("defer2:", i) }() defer func() { i++ fmt.Println("defer1:", i) }() return i } 结果: defer1: 1 defer2: 2 return: 2
跟踪
defer经常用于代码跟踪
func trace(s string)string{ fmt.Println("开始执行:", s) return s } func un(s string){ fmt.Println("结束执行:", s) }
func main() { b() } func a() { defer un(trace("a")) //初始化defer函数的参数,所以输出trace()的结果 fmt.Println("a的逻辑代码") } func b() { defer un(trace("b")) fmt.Println("b的逻辑代码") a() } func trace(s string) string { fmt.Println("开始执行:", s) return s } func un(s string) { fmt.Println("结束执行:", s) } 结果: 开始执行: b b的逻辑代码 开始执行: a a的逻辑代码 结束执行: a 结束执行: b
作者:Fighting社火底子