博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go学习随笔(八)函数参数传递机制\defer和跟踪语句
阅读量:3906 次
发布时间:2019-05-23

本文共 2041 字,大约阅读时间需要 6 分钟。

函数传递机制

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= 0xc0000140a8x= 3  y= 4x= 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)	}}结果:43210

关于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: 2defer2: 3return: 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: 1defer2: 2return: 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)}结果:开始执行: bb的逻辑代码开始执行: aa的逻辑代码结束执行: a结束执行: b

 

转载地址:http://uvqen.baihongyu.com/

你可能感兴趣的文章
从不同角度看机器学习的几种学习方式
查看>>
数据挖掘 NLP 之 文本挖掘 文本处理 通用流程
查看>>
NLP 主题抽取 Topic LDA代码实践 gensim包 代码
查看>>
NLP 工具包 大调查 自然语言处理工具包合集
查看>>
scrapy爬取酒店评论数据
查看>>
各框架下(tensorflow, pytorch, theano, keras)实现几个基础结构神经网络(mlp, autoencoder, CNNs, recurrent, recursive)
查看>>
软考相关英语
查看>>
[老老实实学WCF] 第四篇 初探通信--ChannelFactory
查看>>
ASP.NET 中的 Async/Await 简介
查看>>
解决Chrome中调试JS提示“Uncaught TypeError: Cannot use 'in' operator to search for”错误信息问题
查看>>
阿里巴巴java规范 第一版
查看>>
USB通信记事
查看>>
Android 编译(1)——Android编译步骤梳理
查看>>
编译器配置(1)——ARMv7,ARMv8(AArch64) 浮点配置等相关知识
查看>>
Android 编译(2)——jack-server相关问题
查看>>
网络服务(2)——以太网配置IPV4和IPV6
查看>>
网络服务(3)——以太网phy的识别加载(RK3399)
查看>>
网络服务(5)——usb网卡名称修改(RK3399 Ubuntu)
查看>>
行业观察与理解-互联网巨幕下各行业的现状和发展
查看>>
数据结构与算法大全
查看>>