00:00
我们再来看一下切片里面有一个叫open的内置函数,这个呢用的也比较多,我们刚才在前边是不是已经讲过了,就是。这个切片它有一个特别重要的一个功能。特性就是说它可以动态的增长,这个也是我们使用切片的时候呢,经常使用到的一个特性,什么呢?就是openend,当我们一个切片,你感觉它的数据不够用的时候呢,你可以动态的增长,使用的一个函数就是内置函数叫openend,我们来看看openend是怎么说的。打开我们这个,呃,Build in,大家看这里面呢,有一个叫append的内置函数。大家看这里end内键函数end,将元素追加到切片的末尾,看到没有?如它有足够容量,其目标就会重新分配切它要重新分配切片以容纳新的元素,能理解这意思吧,否则就会分配一个新的基本数组。那也就是说openend呢,就可以用来扩容。那我们来看看它的具体用法。
01:05
我们来举个例子。Open的内置函数可以动态的增加。来,走一个。我们把它先放到这里来,好吧。这些都是我们在使用的时候需要特别留心和注意的地方,我举一个案例给大家说明,这里我们来讲一下。好,假设呢,现在我有一个切片,我有一个切片。我先定一个切片好吧,我先定一个切片VAR slice slice切片,来个切片三好吧,然后呢,他原先的它的切片是这样大的。等于给他来一个切片。给他一些数组吧,比如说100。两百三百,好,这是个切片,看清楚没有,这是个切片没没问题吧,好,那么我们把这个切片呢,给大家输出来看一下。
02:01
Print。Lashan。然后slice输出来,这是一个切片,这个没有没有什么,没有什么问题,我直接给大家输出来看一下。运行一下。好,跑起来。我们可以看到现在切片呢,是一百两百三百,那如果说我们现在需要在这后面再追加一个400,怎么做呢?好可以用这个方式。Openend直接用openend啊end。第一种方式就直接。通过。注意听这句话,通过append。Openend直接。直接给。第什么呢,就是S3。追加或者叫做追追加吧,就叫追加追加追加具体的具体的元素,当然这个元素的值呢,要跟这个类型怎么样保持一致,比如说它是一个int类型的,你就不能给他追加一个float,那肯定就违反了这个数据类型要匹配的原则。
03:08
那也就是说现在我们可以追加是in特,那走一个吧,Openend openend走,然后SLICE3,然后呢,比如说我看追加一个,追加一个400,当然你可以你也可以继续追加,说老师,如果我一个追加不够,我还可以可不可以继续,这是可以的,而且呢,你也可以一次性的追加多个,比如说400,同时我还追加一个500。还再追加一个600可以,这个没问题,好,我们来跑一个,同学们看一下这个效果,诶这有问题,我看哪里错了。哦,他说你没有用过这个是吧,他说你没用过这个呢,应该要接收一下才可以,你不接收不行。就是说他追加完了过后,其实SLASH3本身是没有变化的,再说一遍啊,也就是说他在追加的时候,实际上他是把他是内部做了一个分配。
04:02
创建了一个新的数组来追加的,那也就是说他其实是在十代三追加了三个三个元素过后,把这个新追加的一个东西返回来的。因此你要接收,如果你不接收的话,十来13还是没有变化。能理解为什么,也就是说假设我用四来接收的,注意听。假设我用四来接收的,那我这样接收,大家先看一下。斯莱斯四和十来三有什么区别?注意听讲啊,这块也是一个细节。注意听同学们看到,如果我这样写的话,其实十来是四。应该有。十来是十来14。它是追加过后的元素,它应该是100。两百三百。四百五百六百,但是但是十来三其实仍然还是前三个变数,能理解吧,就是说实际上它这个本身没变化,他只是把它追加过后的东西重新返回一个结果,给给新的一个变量。
05:04
你看这样子好跑起来看一下。我们可以看到十来四发生变化,来三没有变化,但是我们其实需要的效果就是要改变十来三对不对,所以你这样做呢,没有意义,因此呢,一般情况下我们直接用把这个新的这个呢,再重新付给十来13,这样子不就OK了吗?说说。这样子。就是正确的了,好吧,注意这个细节好吗?注意这个细节啊,不要说诶到时间老师没有讲过,也就说我把从重新这个追加过后呢,直接重新付给来三,那S3就真正真正的就就相当于说扩容扩容了再跑一个。跑起来。我们可以看到来三呢,现在应该是最新的数据。对吧,好,这是一个,那么同时之外呢,有些同学老师,我还看到有人这样用,就是open的后面直接来追加一个切片,可不可以也可以,你比如说。
06:07
我在时代13这个基础上。我这样追加。大家看能不能看懂open。我是来三。追加一个新的切片。追加谁呢?我就追加她自己。这个也可以,三个点。注意啊,这种方式大家能理解什么意思吗?就说把切片再追加到这个切片,当然这个后面这个追加的切片可以是十来13,也可以是别的切片,能理解吧。好,这个呢,就是相当于说通过aend追加切片给莱三只。通过append函数将。将切片。将切片。C斯莱斯三。追加到追加。A追加给4S。
07:02
那相当于说自己自我增长吗?自我增长那我问大家一个问题啊。这个十十三,就后面这个十来13,其实也可以是别的切片,比如说你说我我追加一个这这个切片也是可以的,能理解吧,这是可以的,但这个切片呢,呃,我这故意用它相同的切片,就相当说自己追加给自己,那这样做的话,我想请问大家一个问题。那这样子,我们把这个呢,放到下边来,好吧,放到下边来。那我问大家一个问题了,请大家思考,如果我把十来13这个切片再追加给自己了,那后面这个应该是什么样子的?是不是就相当于他原先已经是这个了,再重新复制一份。是不是这样子的12个元素了,对不对,跑一个。跑起来。大家看效果。是不是跟我想的一样呢?来哦,我没有输出对吧,我没有输出。
08:00
我再重新给他追加了切片,过后我没有输出好,我重新再输出一次,请看效果。大家看到这时我们看到效果就跟老师刚才分析的是一样的。他在自己基础上又追加了一份。对不对。是吧,没问题,那么我要跟大家再说一遍啊,同学们,我再说说一遍,就是这个来三,也可以是别的切片。可以是别的切片,能理解吧,可以是别的切片,而且这三个点是固定的写法。就说后面这个呢,必须是切片。不能是数组。注意听这句话,只能是切片,不能是数组,另外呢,这三个点必须带上。啊,你不能,你别别把这三个点忘了,这是我们一种规定的写法,大家记住这个细节就行了。好,这是两种方式给我们的切片追加元素的两种写法,大家注意一下怎么写好,这是我们end的一个案例,我先把这个案例呢给同学们放到我们的。
09:03
笔记里边去。OK。大家看一下,那么关于a pen的内置函数呢?我这里还有几个细节,还有几点说明要给大家总结一下。啊,对。对上面代码的小结,注意听我这里呢,一共总结了有这么几点,大家注意一下切片open的操作的底层原理分析,第一个切片a pen的操作本质,本质就是对数组扩容。这个没什么可说的,就是原先数,原先这个呢,少了,你可以增加几个,第二个够底层会创建一个新的数组,也就是说他在做这个open的时候,其实他会创建一个新的数组。他会把这个新的数组扩容过后。然后再把它重新付给这个新的切片,所以说go底层会创建一个新的数组。OK。那么将slice。
10:00
原来包含的元素。拷贝到新的数组中,看到没有,也就是说它会相建,先创建一个新的数组,这个数组的大小呢,就是按照扩容过后的大小来给你创建,然后再把这个切片,就是你这个准备追加切片的内容先拷贝到这个新的数组里面去。然后让这个slash重新引用到这个新的数组里面去,好注意六二在底层维护程序员是看不到的,也就是说他在这底层怎么去进行这个扩容,创建新的数组,我们程序员不用关心,但是我要告诉大家这个open操作的底层原理是什么样子的。它底层原理其实就是先创建一个数组。能理解吧先,其实这个如果说我们画一个图来说的话,他应该是这样子的一个操作。如果我们一定要画个图来说的话,它其实它底层的操作,它是这样一个流程,我画一次图啊,同学们注意听。
11:03
我以哪个为例呢?我就以追加一个具体的元素为例来分析,就以这两句话来分析好不好,大家注意听。我们来看看这个切片在进行这个追加的时候,Open的时候,它底层是怎么玩的呢。他其实底层是这样玩的。同样,我们先来做。一个内存图。注意听讲哈,我们来讲一下。内存。内存图,那么我们这里呢,我们分析。分析这个end。A的这个底层原理。他其实是这样做的,追听原理,比方说第一次他这有个切片了。看到没有,它这已经有个切片了,那么这个切片当然我我就直接画,我就简单直接画一下啊切片呢。
12:01
这肯定有一个东西,我就四个亿啊,然后呢,这边。那呃,这边有一个引用他的。就是说假设这面有一个slash。注意听啊四三。这个代三呢,它这有三个元素,它这有三个元素对吧。好,我复制一下。好,我把它直接拉过来,好意思意思啊,意思意思这个元素可能跟我不完全对应,我就画个示意图,如果说对照这个的话,它应该是三。这个它的这个容量呢,默认假设就是三吧,好吧,这边假设就三个元素。好,他原先是一百两百三百。好,我就画三个元素,100。200。200。注意听看一下它底层怎么做的啊,300好写完了,那这个时候呢,他们之间是有一个引用的,对吧,它引用到这一栏。
13:04
我画个示意图。引用到这里来的,那当他执行这个open的时候,他会怎么做呢?注意听,那就我们就按这个这这个套路来说,他其实会先创建一个新的数组。也就是说他会先去创建一个数组,但是这个数组在底层里面创建的,所以我们是看不到的啊,这个数组创建的时候呢,呃,这个数组的大小它怎么来判断呢?因为你在这地方有三个元素了,看到没有。是不是他他要追加三个元素,所以说他在这底层呢,它会把这个进行一个扩容。好。好在默认情况下,其实说刚刚创建的时候,其实这些元素都应该是零,看清楚没有。是零,当然这个也是零,因为它一共有六个元素,就是它先前是零。诶,这个地方。
14:00
我们。六个元素是零,好,创建了一个新的数组,创建这个数组过后,它要把slash。这面内存先拷拷贝过来,也就是说他把这个100 200、300拷贝过来,因为大家都知道数组本身是不可以扩容的,所以他根本不可能在原先这个数组上进行这个追加,这是不可能的,底层他也做不了,于是他把100 200、300先拷过来,这边就是100。这边呢,就是200。这边就是200。好,我把这个呢也给大家整理一下好吧,这边就是300。追听那300完了过后呢,后面有四百五百六百,同样也想办法给你拷贝过来了,或者给你复复制过去的,他可能就不是拷贝,它是复制过来的。好的。好,这个时候是不是就是一个新的数组就有了呀。诶,我把这个挪上去啊。好,这个时候这个新的数组就有了,那这个新的数组过后呢,他就看。
15:04
他就看,也就说这个数组本身是没有变化的,时代是30代是三还是指向这里的,看到没有。那关键是就看你要把这个返回的这个新的这个数组交给谁了,如果你是交给十代三的,那这个指针。就会直接指向这边去,那一旦指向这边去,它原先这个十来三这个就怎么样就没有了。能理解吧,相当于说好像扩容一样,当然它这边就会变化,它这边也会变成六,这边也会变成六。能理解吧,这样子就扩容了。当然刚才老师讲到,如果你把这个open的这个值,Open的过后,这个值交给一个十来四。那你原先十来13还指向别的地方,假设我这地方是如如果是十来13,就是这这个刚才的分析,如果你这写的是十来14的话,告诉大家它底层就是这样跑的了。好,我该撤回去。
16:02
如果你是把这个交给十来14,它就会产生一个新的。新的一个来四。它会创建一个新的时代14,这个让这个时代14指向哪里呢?指向这个地方。看到没有?那也就是说你这样做了过后,十来13还是十来13,十来14指向一个新的空间,能理解吧,就看就关键是看你把这个openend后这个返回的这一个数据交给哪个变量,如果你交给S3,那这个呢就指向这边来,如果你交给的是一个新的变量,那新的变量指向它,那原先这个呢,仍然是没有发生任何变化的。能理解吗?好,这是我画了一个示意图啊,同学们自己好好的领会一下好,那么我还是按照我们这个代码画这个对应的示意图好吧,那也就是说,如果按照代码来说呢,我们示意图就应该实际上是这样子的,就没有时来实施的事了。
17:00
他就直接让这个代删。指向这个地方。但当然,因为这个空间已经没有任何变量引用了,那谁会做这个事情呢?这个就变成垃圾了,就会被回收。垃圾。垃圾就会被损毁,就会啊,就会。被回收了。OK,好,那我我我也把这个放到这好吧,我也我也不去把它删掉了,留在这,其实这个地方很快就会被被垃圾回收,呃,被垃圾回收机制回收掉啊。呃,但是你其实你也看到,因为没有任何变量引用这个空间,这个空间其实已经用不了了。好吧,好,我把这个示意图给大家放到这里来。最近这个细节。好的,我把这块呢给大家板述一下。没问题吧,这是我们的示意图。看清楚了啊,看清楚了,好,我把刚才的这几个细节,对他整体的这个说明呢,也给大家一并拿到我们的笔记中去。
18:07
好吧,没问题,好,也很简单。好这块呢,我们就不要这个东西了,我们换成个小点吧。把它板书一下。OK。那这个地方我们怎么做呢?我们把它标成一个粗体,这边我们来一个小点就完事了。诶还切不过去是吧,那就放到这就行了,大家看能看懂吧。好,这个end用的非常的多啊,大家一定要把它底层机制给他搞清楚,搞明白,不然的话别人稍微问你一下,你就搞不清楚了,你也不知道到底是怎么执行的,老师呢画了一个图,把它底层给大家分析清楚了,好,紧接着呢,我们再来看第下一个需要同学们注意的地方,就是切片的拷贝操作。那么切片的拷贝操作呢?他用的是另外一个内置函数叫copy。
19:02
那copy的时候呢,大家看这有个案例,这个很简单。他这样子的。比如说你这里有一个切片。那我就直接直接看代码说话了,好吧,比较简单,这有个切片看清楚了没有,然后呢,我这make了一个切片。这两个都是切片,这个切片的大小是十,在我们没有默认没有给值的时候,大家想一想,默认是不是全部都是零呢?一共有几个零?是不是有十个人?十个里。那么有十个零过后呢,你打印出来肯定就是输出这个玩意儿,123456789,还有一个零。四个零,那这个时候呢,他用了拷贝,这个拷贝的意思是什么意思,就是把这个A。A的这个数据拷贝给这个slash。注意啊,你原先这个A,比如说原先这个切片,它自己是有个空间的,它是一。
20:01
二。三。四五。现在这个slash也有自己的一个空间。这两个空间是独立的,再说一遍啊,你有你的空间,我有我的空间,这两个不打架,然后呢,Copy就把A里边的数据呢,数据拷贝到十来,也就是说它会把12345分别拷贝给对应的位置,那就说这边变成一,这边变二,这边变三,这边变四,这边变五,能理解吗?那后面这几个怎么办呢?不怎么办,保留原子就行了。为什么保留原子?因为因为你只有五个拷贝给他吗?那后面我还有五个,那我就保存原来的子就可以了,还是五个零,能理解了吧。这就是拷贝的操作,拷贝的操作不难吧?好,那既然如此,同学们我们来看一下这个代码是不是跟老师分析的一模一样,还有一个细节,这个拷贝呢,它必须要求都是切片才可以拷贝,不是数组。
21:02
这地方大家注意啊,是切片类型才可以执行,才可以执行这一个什么呢?拷贝操作不是数组。好,我把这个呢给同学们举例说明一把。来跟上老师的思路。好的。我举个例子。就以刚才这个案例来举例。好切片的拷贝。嗯,我们新建一个数组吧,新建一个数组。All right。然后呢,Slice,比如说我建一个四这个切片好吧,Int。好,这个切片我就直接给它附一个值,初始化一下,比如说一二。这边打个空格一二。三。四五写完了,然后呢,我在用make的方式创建了一个切片。
22:00
那就直接这样写了。对吧。Make。Make什么呢?类型就是这个切片的类型,然后呢十个。对吧,Make make完了过后我执行一个拷贝Co。然后呢,我要把这个SLASH4。拷贝给莱五。没问题吧,好,现在。现在呢?现在我们把它这个输出来,大家看一下print LN,那么我们先输出来四。S4等于好输出来看一下。我们也把时代15说出来一下。好,同学们,想一想,这个地方应该输出多少?这个地方是不是输出12345,下面应该输出什么,根据刚才老师说的应该是123。
23:05
是。五后面还有几个零一个两个三个。四个五个能理解吧,刚才我已经分析这个原理了啊,那么我们来跑一下。为了比较好看呢,我们仍然给他来一个换行,对不对。跑一下这个逻逻辑走跑起来请看代码。我们可以看到跟老师分析的是怎么样完全一样的。他们是独立的空间,对不对?它们是独立空间,我问大家一个问题啊,我修改SLASH4的元素会对SLASH5有没有影响,大家考虑。比如说我修改十来四,把这个来四这个二换成20,请问S来SH5的这个二有没有变化?显然它是没有变化的,因为他们是独立的空间,能理解吧,他们数据是独立的好不好?这个大家一定要注意啊,这块我就不去举案例了。
24:02
再说多说一句,他们之间的数据是数据,空间是独立的。好,我把这个拷贝操作给大家放到这边来。这是我们的代码。OK。好,举例说明,那么针对这个代码呢,我们有几点重要的说明给大家整理一下。对上面代码的说明。上面代码的说明。上面代码的说明。好,我把它整理一下啊,有几点需要同学们注意的地方,我整理一下第一点。第一点就是。嗯,在进行拷贝时,在进行拷贝时要求这两个参数都是切片。Copy。Copy有两个参数,PART1,还有一个PIRATE2,不,这两个参数呢,要求都是界面参数的类型,就数据类型呢,类型是切片。
25:07
对吧,第一个第二个,第二个就是说,第二个就是说什么呢?他们按照我上面这个案例来说啊,按照我这个代码来说,他们数据是相互独立的啊,按照上面的代码。按照。按照上面的代码来看。来看什么呢?就是SLASH4。和斯莱五。的数据空间是独立的。独立的相互不会影响,就是你改变了它不会影响到另外一个地方,相互不影响。相互不影响。不影响。也就是说也啊也就是说,也就是说,说什么呢?说。就是如果我这个sla是。
26:00
我给他这样做了一个修改零,我把这个零这个它的第一个元素给它改成了,比如说改成了这个999。那么来五仍然是一。那么十来15。时代是五的第一个元素,并没有发生变化。最听这个细节啊,仍然是。对吧,仍然是几呢,仍然是一。哦,我不会。受你的影响,好这块需要同学们注意这两个细节,好这地方我把它整理一下。好这块,因为他这已经有这个下标了,所以说这个地方呢,咱们得用这种符号才可以,不然的话到时候可能就区分不了了,好吧。注意这个细节,好,同学们,那关于拷贝拷贝的这一个内置函数,还有a pen的内置函数的说明呢,就给大家先介绍到这里,这块也是我们在切片使用的时候需要大家伙注意的地方。
我来说两句