00:00
我们接着来看go函数注意事项和细节讨论。那么在go中,函数也是一种数据类型,就是函数本身它也是一种数据类型,可以赋给一个变量,该变量就是一个函数类型的变量了。也就是说,Go函数本身也是一种数据类型,它的地位和我们的int尺寸是一样的,就是都是数据类型,能理解我的意思吧?好,那么我们来看看,那么我们来看看怎么来领会这句话,那我把这句话呢先放到笔里面来,我们举个案例说明好吧。这是第八点。每个细节都很重要啊,我就说一下,函数也是一种数据类型。这一点先给大家明确下来,第二点呢,它可以赋给一个变量。该变量就是一个函数类型的变量,而且通过该变量呢,可以实现对函数的调用。来吧,举例说明,大家看老师给出的案例,比方说我有这么一个题。
01:03
我新建一个。同学们,我新建一个文件。叫做DEMO,呃,DEMO04DEMO04吧,04DEMO05了。担保零五。细节的东西就是这样子的,好像有点繁琐对不对,但实际上呢,他又是特别重要的。因为你不了解细节,后面你在做开发的时候,你会突然发现跟别人不在同一个层面上,别人知道的你不知道是吧,那就麻烦了。那显然你这个工资也很难提上去。对不对,好,我把这个呢给同学们放在这儿,所以说我们在学细节的时候,大家要特别的认真。啊,认真对待,我们说一个程序员水平的高低,其实主要还是看细节,越是有经验的程序员,他了解和知道的细节就越多,他才能避开在使用函数的时候有哪些陷阱,以及它也能知道怎么去用函数,才能用的更加的高效,对不对?那我们来看看这一块老师要讲的呢,就是这个细节。
02:07
我把它先放到这里来。我们把这个细节放到这。其他细节也以此类推。OK。给大家来一个注释。那同学们看,我在这里先写一个函数fun,我就像我写一个sum,就是求它的什么呢?求它的和求两个数的和N1。来了,看这样子啊,我们写个get。Get上好吧。N1。In n2。也是一个int没问题吧,然后呢,它会返回一个int值。写完了,然后我在这里写一个N1加N2完事,非常的简单,非常简单,但是我这里想说的函数本身是一种类型,怎么来体现呢?注意看效果,假设我这有个A变量,我就随便写的啊。
03:04
A变量。然后呢,我把这个函数直接付给他,大家来看一下。大家来看看这样子语法会不会报错,我把它输出来print f,我输出一下A的。类型是。类型是。我把它输出来啊,同学们请看T。然后呢,我把这个干上。这个函数的类型。也输出来。类型是。百分之T,那我怎么来说呢?把A的变量和sum函数直接写到这,我们来通过这个看一看它会打印出什么样的信息。CD点点上一级,然后CD到FUNCTION05。Go,让命点go跑起来。我们可以看到,在这里它会输出A的数据类型是这个。
04:03
大家看到了吗?是不是它是个函数啊,Get上类型也是这个,你看他们两个是一样的,因为你把get上交给了A嘛,你付给了A嘛,所以他们呢,其其实他们他们都相当于指向了同一块的代码空间,代码空间那我还能够通过该变量实现对函数的调用,你看我可不可以来吧。我写一个。对于。A。A,它就是一个函数了啊同学们,我负一个十,再负一个40,其实这个就等价于绕。等于,等于多少呢?Get上。然后。十四十这两个是等价的。因为我刚才讲过了,你已经把这个函数付给了A,其实他们两个都指向同一块代码空间,能理解吗?
05:02
也就是说他们是可以这样调用成功的,我把它输出来看一下。好,我输出res等于它的值,看是多少,应该是等于50对不对。好代码写完再看效果。是不是等于50啊,诶,这地方。没有换行。再跑一遍。再跑一遍,这样看的更清楚了,Res等于50成功。完全没有问题,所以说从这里我们就就体现出在函数里边,在这个go里面啊,函数也从数据类型,它可以把这个函数交给另外一个变量,并且通过该变量来完成调用,这个特性在后面我们还会用到。比如说在讲必包的时候,我们还会用到这个特点,好吧,好,这个细节的案例先给大家拿到笔记里面来跟上老师思路。我把这块的细节拿到笔里面来。
06:01
OK,每一个地方咱们都有案例说明。写完了,那现在我们再来看第九个细节,各位朋友,第九个细节是函数既然是一种数据类型,因此在构中函数可以作为行参并且调用,诶,有点意思了,就说我们前面的形参数据类型呢,基本上就是基本数据类型。而且。而且也可能是引用类型,但是把函数本身当做一个形参传过去呢,好像没有用过,那我给大家举个例子,举例说明。那这次呢,老师就直接在前面这个案例上来玩一把,我写一个,我写一个函数,把它当做一个行参来接收。写一个吧。来看案例啊,跟着老师思路,比如说我有个my function。测试的,然后呢,我有一个变量,VR我就随便起个变量啊,比如说放VR随便的啊,就是随随便取这个名字,随便取叫ABC都可以,叫ABC都可以。
07:05
那这地方呢,我要来接收一个,我想我想让这个变量变成一个函数类型。那怎么写呢?非常的简单,放。然后定义一个,把形参类型写清楚就可以了。一个int,两个int,还返回了一个int,看这个刚才不是打印出来,我们这个get上的函数类型不就是这个吗?那我这。放VR的数据类型就是它,然后我再传两个整形过来,一个是NUMBER1。再来NUMBER2 int写完了,写完了过后,刚才我们老师老师刚才讲过,如果我们把一个函数交给一个变量本变量本身也可以调用,对不对,那这直接return,大家看我这样写可不可以直接把number一传进去,再把number二传进去,可不可以?
08:00
其实这句话呀,完全可以运行。因为刚才我们不是有一个知识点了吗?我们可以把一个函数交给一个变量,那同样我也可以把一个函数交给一个行参,通过行参来调用这个函数不就完了吗?好,请看案例。看案例。好了,现在我们来写一个RESULT2。等于什么my phone,然后我把谁传进去,大家猜一猜,是把盖上。该上是不是做一个函数传给了我们这个行参,传给这个行参,我再传两个值过去,比如说是一个是50,一个是60。好,我把RESULT2这个字输出来。大家猜一猜是多少?是不是就是50加60并返回了这个流程,大家再想一想。再想一想怎么回事?是不是你把这个函数传给了VR?
09:01
把这个50和60分别传给了一个是NUMBER1。一个是NUMBER2。然后呢,这个放YVR呢,就是这个函数了。是不是就是该上面的函数,然后你调用,调用的时候再把这两个值传进来,这个就变成50。这个变成60,最后一加,加起来过后这个等于多少110110,再把这个return返回给这个位置。那res就应该等于110。最后对方输出也是110,分析完毕。能理解吗?这个我就不再多说了啊,同学们,这个你还绕不过来的话,就把刚才老师讲的函数调用机制再给我走一遍,对方是不是这有什么问题,是不是它要返回一个值,你这还少了一个什么int?写完了。来,朋友们执行一下吧。RESULT2是不是等于110跟老师分析的完全一样?我再多问一句,同学们,如果我把这个冒号去掉行不行?
10:02
如果我把这个冒号去掉,这个就相当于把这个返回值交给res,可是你res定义了没有,你根本就没有定义,这个肯定会报错啊,他会报告你RESULT2RE2没有定义,看到没有,如果你一定要这么用,因为我们。第一次学,呃,有些同学第一次接触构语言,他对这个语法不熟悉,对吧,那如果你一定要这么用,你可以这样写,你在前面先定义一个。就是int res2啊这样写的RES2 int这样也可以。要先定义了,然后再把纸付给他,但是这样写有点麻烦,所以说老师呢,一般来讲我就直接用的类型推导。就完事了。好,这是我们讲的第二个细节,看懂了没有?我把第二个细节给同学们放过来。来吧。好,这个地方是老师的这个第一段代码。我截取的是核心代码啊,核心代码。是不是?
11:00
我把这些地方。写过来,然后我们函数的调用。My phone是怎么定义的呢?卖方是这样定义的。对吧,是这样这样写的,看这里。不说了吧。还是比较简单,大家一看就知道是怎么回事了。好,这是两块核心的代码,第十个细节我们看一下。为了简化数据类型的定义呢?Go支持自定义数据类型。这点在很多语言里面是没有的。够支持,其实这个呢,是C语言里面的一种语法现象,被他拿过来直接用了还是比较好的,它是怎么样来进行自定义数据类型呢?它可以支持自定义数据类型,这个还是非常有用的啊。你比方说它的基本语法是type。自定义数据类型名,然后后面写上数据类型就可以了。你可以理解成好像给他取了一个别名。
12:00
可以这样理解说,好像给他取了个别名,比如说第一个案例type my int,这个就相当于说my int就等价于int了。同样我也可以把一个函数。类型定义成一个。别名,比如说type my song,然后呢,Function int int,返回int,这时my song就等价于一个函数类型,什么呢?这个类型,这个类型就是不是你这写的吗。对吧,非常简单,来老师给大家举几个例子啊,跟上老师思路。这个还是用的比较多的,尤其是我们有些同学刚刚接触这个构语言,还不太清楚这是怎么回事,所以大家认真听。我把这个往后面挪一挪,举一个案例吧。好吧,举例说明。来举个例子给大家。举例说明这个自定义自定义数据类型的使用。个人思路,那么我把这块给大家写两个案例。
13:05
使用一下好不好,来看一下案例。还是在这写好吧,我们就不写那么多了,就在这写。比方说我这里有一个变量,注意听讲,VR my inch inch。好,这个呢,就是相当于给这个int取了一个别名,取了别名。啊,别名。但是我要给大家说一下啊,在go语言里,在go语言里面来看呢,Int和my int它不是同一个类型。就是你不能完全把它等价于同一个啊,就他认为这两个还是呃,不同的数据类型,一个叫my int,一个叫int,能理解吗?这个有点怪,但是他确实这样这样做的啊,就是说相当于呃,相当于这个my int和int,他们都是int,但是呢,他认为是两个不同的数据类型,这点我说明一下啊,在各种。
14:00
在购中。在构中这个my in。My inch。和int虽然啊虽然。虽然都是都是特类型。但是。类型,但是这个go认为呢?认为他们还是两个不同的数据类型,认为my in。和int。不是还是两个啊,两个类型啊,这点大家注意一下就行了。虽然他们都是硬的,但是他是他从语法上来看呢,他认为还是两个不同的类型。好,我把它放到这里来。那我给他举个例子吧,同学们看我这样可以举例了,比方说VR,我定一个n number,比如说我写个number。Number几呢?好,就是NUMBER1,那么my in。那这个就一样可以用啊,那我给大家来。测试一下,比如说NUMBER1。
15:03
等于40。来看效果,那我直接。把这个NUMBER1输出来,大家看一下。Number等于NUMBER1。那这个时候呢,应该输出挤压输出40就可以了,跑起来了。诶,这有问题啊。Format。PR写错了。PR。再看一下。Print这方为什么错了,看一下。My inch。哦,怎么这样写啊,不好意思,这写错了type。好,这样才是定义啊,Type来,跑起来,同学们。运行起来提看效果,这时候我们可以看到NUMBER1等于40就出来了,但是大家注意,我刚才说了一句话,够认为这两个是不同的类型,那怎么来证明这个事情呢?可以这样证明,打个比方,同学们注意听,注意听啊。
16:01
假如。我有另外一个类型叫NUMBER2,我写的是。就是特,那么大家看我在赋值的时候NUMBER2,我直接把NUMBER1给他,你会发现这个地方会报错。你看我保存一下。大家看这里。看到报错了没有,他说不能够,不能够把这个my int直接付给int,因为他认为这两个不是同一个类型,所以说,但是说老师也说,有些同学可能不理解,说的不都是特吗?为什么呢?因为go语言从语法上认为他们两个是不同类型,因此你要把NUMBER1交给number,就相当于把把my int这个类型交给了。Int这个类型他认为是不允许的,那怎么办呢?转一下就行了,一样一样的规矩,比如你特尔是这个,那我就转。转了就行了,这样就可以了。看到这里没有?这就可以了,好这里呢,因为你这NUMBER2没有用嘛,所以它会报错啊,它会报错要把这个NUMBER2也输出来。
17:04
NUMBER2等于NUMBER2,代码写完了。代码写完了。注意这地方我再强调一下啊各位。各位注意这里,注意这里,依然依然需要。需要强转转换。啊,显示转换,显示转换。啊,因为什么呢?因为够认为这两个是不同的类型。OK,理解了吗?理解了啊,一定要显示强显示转换,否则要出错的。好,那么这时我们就把这个,把这个细节给他说了。那么我们再来举个例子。举个复杂一点的例子就是。呃,我们来定义一个函数,这样可以简化啊,可以简化我们的使用,来手一个。再举一个案例,我把第一个案例先给他整过来吧。对吧,先把这个第一个案例整过来。不然的话,案例太多了,容易我在截图的时候也容易写在一起。
18:05
好,我把这个地方写一下。好,这个案例是讲的他对不对。好,我把它放在这里好吗?接着我们再来看下一个。下一个呢,就是,呃,我们再举一个例子,就是把一个函数给一个函数类型取个别名,那么这样写一个好处就是将来如果我们这个函数做一个行参的话,就可以简化了。就可以简化这种写法。来举个例子。再举一个案例啊,再举。再举。举一个案例。再加一个案例也可以,那假设我先这样写了啊,太婆。Type my phone。然后呢,这个函数类型呢,是这样写的,Fun。In,诶,写错了,Inch inch。
19:00
Int。那也也就是说这个my phone呢,就是这种函数类型的,这个能理解吗?就这个时候,这时。这使这个my fun。就是。就是什么呢?他就是这个类型的。能理解哈,注意听讲类型。那我这个写法有什么好处,你看原先我们这个写法是不是写的比较长啊?是不是写的挺长的,现在如果有了这个东西的话呢,诶两个都叫麦放,有有要出问题啊,两个都叫麦放的话不好,那我这个地方就写一个新的。Type吧,加一个好吧,MY方type好,那如果这样写的话,我们这一段这个定义就可以这样玩了。来是不是原先。原先我们自定义我我们这样写的船的话,这个就特别长,去掉换成什么呢。
20:00
换成这个。换成这个也可以用,看到没有。那人完全一样,就是老师,诶这个你因为我不这样讲的话,以后你看别人写代码你看不懂,你突然发现,诶这是个变量,这个什么玩意儿,结果你一查,哦,My fun type是一个这个东西,你你瞬间就蒙圈了。对不对,说老师不讲是不行的,因为咱们既然要当程序员,你其实你就是要抠细节,你不抠细节,你跟别人不在同一个层面上,知道吧,就别人知道的,你你不知道就麻烦了,那么我们来用一用,我们来用一用,看看这个这样写能不能用起来,对吧,能不能用起来,对不对,好我我这就偷个懒了,好吧,我就直接。把这个拿过来,把函数改一下就行了。放二。是不是传过去了,50这个改个名字吧,50,呃,五百六百。完活了,这个地方改成RESULT3好吧。改成三,我们看看这样吊起来没有,大家看啊,这时我传的是get还是传的get上,该传给谁了呢?传给这个家伙了。
21:05
啊,传给这个家伙,因为my fun type是我自定义的一个数据类型,好,我们看看能不能跑起来。能不能跑起来保存?保存那大现现在看啊,问题在哪里呢?因为我这个type是写在里面的。其在这里面的,我在外面,我在外面用,我能不能用还是个问题,你想想你在这个函main函数里面定义个type,人家在这用的,它能识别没有,它根本识别识别不了,所以说你在这个地方呢,你只能把这个东西怎么样。提到外面去。你要提到哪去,至少你要提到他的这前面才可以用。你不然的话,编译器怎么知道my fun type是个什么玩意呢,他肯定说这个没有定义过嘛,对不对,所以说我把它提到前面去,这样用就没有任何问题了,来把代码整理好,我们保存一下。
22:00
看代码这个红色的波浪线是不是就没有了来保存。请看效果。代码没毛病的。正确了,来跑一个吧,跑一个走着跑起来。RESULT3应该等于多少呢?1100,完全正确,好,我把这个呢也给同学们拿到笔里面。好,我把这个也给大家拿到笔记里面来,注意听讲。这一块是吧。诶这一块,然后呢,也把它放在这块,这是第二个案例。稍微的整理一下笔记。然后呢?然后我把它的调用这块代码也拿到笔里面来。是不是这块代码,看案例这块代码。好,也把它整理到笔记里面来,没毛病吧?好,整理一下好。OK了。好,那这两个案例呢,我们就说好了,这块我加个。价格波浪线,好吧,价格波浪线。
23:02
哟,这变黄了。好把它退出一下啊,退出一下。好,没没问题了吧,没问题了,那个不能写。表示的是第二个案例。这是我们说的第11个,第十个细节,我们再来看一个第11这个细节,这个呢也是有点用处的,呃,在很多时候我们需要用到这个。特性,它go语言里面啊,它支持对函数返回值命名。比如说我们前面有一个函数,要计算两个数的和,和两个数的差,我们当时呢,直接写的是int和int,但是有时候呢,有些程序员他喜欢直接给他命名,就说。我直接为这个返回值命名,能理解吗?那就是说我这儿。写个some,这是sub,到时间你你不用在这个返回地方再写,要你你这不用再写,要返回哪两个值了,直接。
24:03
这个地方就是对应关系,这这你看这。你这玩不是一个sum吗?好,我在这里面直接就把这个sum给算出来,再来一个sub,你这不是sub吗?好,最后来一个return就行了,后面就不用再加,就不用再加,诶还有一个什么sub,还有一个这这个一一个sub和sub就没有了,这样有什么好处啊,这样就说顺序我无所谓了。知道为什么吗?因为你原先这个有个顺序关系,现在无所谓了,只要名字给它对应上就可以,好,我把这个呢也给同学们走一下。支持对返回子命令。那我举个例子。同学们跟着老师思路啊。我们。跟上老师思路。好的。来。再举个例子说明一下。老规矩,我在这里写一个函数。来吧,放我们再来一个叫get some。
25:04
And。Sub。然后呢,我让他传两个值进来是吧,N1N2。是不是也是int呀?我们以前的写法是int int2个值。以前传统的写法是这样写的,这种写法呢,有一个问题,就是你必须把两个数的顺序搞清楚,不然的话和或者是差可能刚好刚好求反,那怎么办呢?也可以这样写,比如说我写一个S。Sub就叫呃萨,然后呢,这边是sub。可以,那我在算的时候就可以这样算了,同学们注意,这个语法也用的很多,等于N1。N1加N2。注意这里这个地方就不要再加这个东西了,不用再加了,为什么呢?因为你这已经把这个名字定好了,相当于说在它调用函数的时候,它把这两个,这两个返回值也给你创建好了,就相当于说在我们的这个编译器在调用这个函数时,他把这两个。
26:10
返回值的创建工作也给你做好了,只是它默认为空,默认为零嘛,对吧,默认为零,好这们不要写这个,写写这个东西了,好sub。Sub。等于N1减去N2,最后呢,你就return就行了,你不用再写这个了啊,说我写个这个没有必要了,没有必要直接return就行,而且这个好处是什么呢?就说。因为你这个sum和sub呢,这个值算出来是多少就是多少,所以要跟他顺序无关了,比如说我把这个顺序调一下。我把这个顺序调一下,那你上是多少还是多少,上是多少还是多少,对不对,只要你在那边接收的时候按顺序接就可以了,能理解吗?好这次就没问题,好我来试用一下。给大家演示一下啊,跟上思路。
27:06
看案例,看思路,比方说我现在有个A这个值,还有个B这个值。等于。这个。然后我传一个值,一个是一。一个事,那我问大家一个问题,A等于多少?AA是不是就是按照你这设计的,你这样返回的第一个是sub啊,Sum就是两个数的和第二个是sub对不对,至于你这怎么算的顺序,我我我不关心,反正第一个就是sub,呃,一个第一个sub,第二个sub。OK,好,现在呢,我把它输出来。表演铁人。来吧。A等于。百分之我这是格式化一下。再来B等于百分之V,然后把A和B输出,最后我们来一个斜杠N。好,同学们,代码写完了,我们跑一下。
28:00
跑起来。好,这么有一个问题啊。他报告我们。哦。我看这里面是什么意思。不能够分配什么什么哦,它是两个两个。没问题啊,A和B。S。这不是有两个值吗了。Return。Sub。好,我们来看一下这个问题是出在哪里了。好,同学们看看这个原因,大家看出来是什么了吗?有没有发现这个A有问题?因为这个A我们在前面是不是定了一个A啊,这个A它是函数类型,因为我我这个名字重名了,所以他报的是这个意思,你不能说他这他这样理解的话,他认为你把这个返回的这个sum交给这个A,而你原先那个A数据类型是什么呀?是函数类型,所以这就不对了,明白吧,那就这样子,我们换个名称就行了。
29:02
这样就可以了,对不对。因为不要跟前面的名字产生这个冲突嘛,这样就没问题了,跑起来。走着,我们可以看到A等于三,B等于负一,完全正确。好,我把这个呢也给同学们整理到笔记里面来,注意听啊。我们这次讲的是函数返回值是支持命名的。给他整理到我们的代码里面来,OK,没,没毛病吧?写字。然后我把调用的方式也给同学们整理到笔里面来。是这样调用的吧。走着。案例。好。Ola。好,这是我们讲的第11个细节,那这里面呢,这个视频里面我们又讲了这么几个细节,大家再过一遍,第一步函数也是类型。可以赋给一个变量并调用函数,既然是数据类型,可以做行参。
30:02
第11个我们讲到函数呢,它支持这种自定义数据类型。对不对,这这个用法在我们后面用的非常的多啊,非常的多,11个函数返回值支持命名,这个呢,用的后面也用的很多,好关于这八九十十一,大家好好的想一想,回忆一下,然后呢,看一下这个笔记,那关于这一部分的细节呢,先给同学们介绍到这里。
我来说两句