我是靠谱客的博主 飞快星星,最近开发中收集的这篇文章主要介绍go 当参数是slice,传值还是传指针?总结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

下午面试,面试官让我写二叉树的中序遍历。

遥想半年前的秋招,我还只会C++,做啥题自然都是C++。

半年后的今天,经过了几个月的go语言学习,go学的咋样不敢说,反正C++是忘光了。。。

经过几秒钟的思考(其实我是想先定义个二叉树的结构体,可是实在是想不起来C的结构体怎么定义了。。。),我毅然决定,用go来写!

讲真,这是我第一次用go做题(别看我已经写了那么多篇go的文章,仿佛自己是个go语言专家)。。。好在,中序遍历的递归写法实在是没啥难的,所以,我很快就写出了下面这段代码:

func inOrder(root *TreeNode, array []int)  {
	if root == nil {
		return
	}
	inOrder(root.Left, array)
	array = append(array, root.Val)
	inOrder(root.Right, array)
}

面试官看了看,给出的评价是,恩,虽然细节上有些问题,但思路是对的,嘿嘿,那当然了,这我还能写不对,等下!细节有些问题是什么鬼???就这两行代码还能有错???我心想,肯定是这个面试官不懂go语言,随口一说的,所以当时也没追问这件事儿,万一一追问,他说他不会go,多尴尬啊对吧,哈哈哈。。。

然鹅,我是一个严谨的人,面试结束之后,我还是决定亲自跑一遍这段代码,用事实证明,我这几个月的go,不是白学的!

首先,我输入了一个这样的树:

这个中序遍历完,array那个slice应该变成[1,2,3,4]。

然鹅,结果是这样的:

卧槽,怎么是个空的???

我开始努力回忆初学slice的时候,当时我还写过一篇blog啊,怎么会搞错呢。。。

这段是当时我当时写的,看来看去,没错啊,slice里面存的是指向数组的指针,所以传slice的值进去,也是可以改变底层数组的啊,为啥我那么写就不行呢???

百思不得其解的我,百度了一下slice作为参数的用法,看到一个人说,如果slice在函数内部扩容了,就会#¥$&(他说的我没太看懂。。。) ,是啊,我给函数传进来的是一个容量为0的slice,在append的时候会扩容,而扩容的过程是:

  • 先分配一段新的内存
  • 然后把原来数组的内容拷贝过去

想到这儿我开始有些动摇了,可还是没有完全想明白,我看了下我的代码:

array = append(array, root.Val)

append的时候确实扩容了,slice里的指针也确实是变了,可是变了之后我又把新的赋值给array了啊,这个还是我外面传进来那个array啊,所以函数执行完外面那个array应该被修改了啊,没毛病啊。。。

这时我突然想到,array我是以值的形式传递进来的,也就是说,array里那个指向数组的指针,也是以值的形式传进来的,也就是说,函数内部修改了这个指针(注意是修改了指针本身,而不是修改了指针指向的内容),外面是看不到的!!!

阿西吧,原来如此啊。。。

于是,我把函数改成了传递slice指针进来,像下面这样:

func inOrder(root *TreeNode, array *[]int)  {
	if root == nil {
		return
	}
	inOrder(root.Left, array)
	*array = append(*array, root.Val)
	inOrder(root.Right, array)
}

再一运行,终于是对了。。。

天哪,我之前竟然还自信的以为是面试官不懂go,我简直就是个傻屌。。。

总结

最后总结一下吧,slice作为参数,如果以值的形式传递,确实可以在函数内部修改数组,但前提是,函数内部slice不会扩容,如果函数内部slice会扩容,那还是乖乖的传slice指针进去吧。

最后再说一句,我真的是是太年轻了。。。继续努力吧。。。

最后

以上就是飞快星星为你收集整理的go 当参数是slice,传值还是传指针?总结的全部内容,希望文章能够帮你解决go 当参数是slice,传值还是传指针?总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(52)

评论列表共有 0 条评论

立即
投稿
返回
顶部