00:00
我们来看一下方法和函数的区别。我认为方法和函数的区别呢,主要是三个方面,第一个呢,就是调用方式,大家发现它是不一样的,有没有发现你比如说函数的调用方式呢,他就直接通过函数名,然后传时参就可以了,是不是方法的调用方式呢,它首先得有一个变量,当然这个变量应该是和方法绑定的这个类型的变量才可以。然后传入实际参数,这个呢在前面已经说过了,对吧?第二点,对于普通函数接收者指为值类型的时候,就不能将指针类型的数据传入。反之亦然。这句话什么意思呢?就说如果我是一个函数。那么。他如果是指类型,你就只能传这个指类型,他如果是指针类型,你就只能传指针类型,这点呢我给大家整理一下,比方说现在我们来看一个案例。
01:00
还是看一个案例来说话。还是按一个案例来说话好,我新建一个文件夹对吧,我们叫method Vs什么呢?Function。好,我们来看看它们之间的区别在哪里。问顶购。背顶好,双击一下。一。这个地方。变成这个删除啊,删除一下可以建成文件夹了,对吧,建一个文件。main.go。好,我从这边粘一份代码过来,大家注意观察。对不对,大家看啊,假设现在呢,我有一个结构体叫person。Structure。Person。呃,Type啊,就是写错了type。
02:03
Type。Person structure。好,我给他一个字段叫name,然后假设呢,我这里有一个。我这里有个主函数,大家看,嗯,现在呢,我这写了一个函数。我再写个函数,比如说这个方程叫做什么呢?叫TEST01,然后呢,我在这里定义了一个这样的类型,Person。没问题吧,然后呢,我输出一句话叫P点什么呢?P点这个name就完了,那现在呢,我在这定义定义一个person,这个比较简单,我就直接写了,好吧,Person。然后呢,我给他一个值,比如说叫做汤姆。然后呢,我在调这个函数的时候,我这样调是不是零一,因为它这是结构体类型,并不是指针类型,因此呢,我传的就是P,好这个呢就是正常的,那我们来运行一下。CD。
03:00
可下CD到chapter。010对不对,DRCD到method Vs。好,Go wrong。Main函数抛起来,我们可以看到呢,这个时候它的结果是吧,跟我们想的一样,就是汤姆是正确的,但是这个时候大家看到,因为他这就是写的person,因此你就不能传地址。看到没有,你不可以传这地址,你传这个地址的话呢,他就直接报错了。看那边已经报红色了,看代码肯定是错的。对不对,代码是错的,所以说我们得出一个结论是什么呢?就是这么一个结论。就是如果是函数。那你这个地方。对吧,那你这个地方如果你是指类型,Per值类型,你就就不能将指针类型,就是将这个地址传给他,你不能传个地址过去,对吧,反之亦然,你再比如说大家看。
04:01
如果你这有个T02是个函数,但是它是个指针。它是指针,你在调test的零二的时候。你就你就只能传一个地址,你你像这样传P1。对吧,当然因为它是指针,你这样去用的话呢,看他能不能这样用啊。你看这样这样子,这样子传一个P1P1你看这样子也是可以的是吧,我传了一个地址给这个指针类型,它也跑起来了,那我们看看这样子运行有没有问题呢?我们发现。看这里。这系统不能只这文件没找到吗。Go,让命跑起来。可以看到这两个结果都是一样的,对吧,汤姆汤姆,那这个时候你看啊,因为它是指指针类型,你就必须传指针,如果你传这个呢,它也会报错。你看他也会报错。看到没有报错了吧,所以说他这就有一个严格的规定,就是反之亦然,就即他如是指针,你就只能传地址,他如果是指类型,那你就只能传职。
05:06
但是我们要说的是,这个方法呢,它不一样,比如说你给structure写一个方法,接收者为值类型。如果他这个接收者是一种类子类型,可以直接直接用指针类型的变量调用,该方法反过来也是一样,也就是说你既可以传,你既可用指针类型调用,也可以用这种指针指类型调用,反过来也是一样,就说如果接收者是指指针类型也是可以的。这句话有点不好理解,我要把这个呢好好给他说一下啊,不然的话,你以后看别人代码,你会突然感觉到好像感觉看不懂似的。这个地方看起来好像很啰嗦,其实很重要,我再说一遍啊,其实很重要,你你看我再写给这个person定义两个方法,注意听放,然后呢,我这样写啊P。Person大家看到这个地方我是直接写的指类型对吧,不是指针类型,然后呢,TEST01TEST03。
06:04
零三来走一个。然后呢,我在这里输出print p点内。这个也没问题吧,我把这为了以示区别呢,我写个TEST03好不好,注意听。啊,等于好写完了,那你你们看到在我调用的时候。他是一个这个地方,它是给person这种类型绑定的一个方法,对不对,那所以说我这样调,我这样调肯定是没有问题的,我相信同学们这点应该不用怀疑,我用test的零三去掉这个肯定是没问题的,跑一下。跑一下,我们发现他也输出汤姆,但是你会发现你这样叫它也可以。你说这样叫他也可以?你看。也就是说你这个地方是通过这个你你给这个P取了一个地址,然后调T03也可以,为什么呢?因为他这个编译器也做了一个优化,也就是说。
07:01
也也就是什么意思呢?就是说你虽然这个P绑定的,但是呢,我传一个地址也能调你个零三,但是它传进去过后,这方这个地方仍然是进行进行了一个拷贝哦。这地方就特别容易出题来考,你你看啊,你你们先看效果。你们可以看到他打印出两个。对不对。而且你你会发现你虽然这方是填填的地址,你们可能会认为这这种方式啊,一般的人都会认为用这种方式调用完了过后,这个P是指向这个外面这个P其实不难,它仍然是一个纸拷贝。曾经有一个非常非常,这个容易混淆的面试题就是在这发生的,就在这出了一个题,你,你们看,假设我这样改,你们会认为会有什么现象,那我把它改成Jack。改成Jack了,好,同学们想,同学们想一想啊,嗯,如果我用P。点点T03,大家都知道这是一个直拷贝,那你这个地方J的改变肯定不会影响到外面的汤姆,对不对,这是肯定的,那比如说我在这说一句话。
08:10
注意听啊,我这写一个叫做P点内。P点内追听。好,这地方命啊,为了一时区别,写个me等于。多少呢?就P点内没没问题吧,没问题,好,你们看这掉落完了过后,这外面这个men p点内仍然是汤姆。肯定是肯定是汤姆,因为它是只拷贝嘛,诶我看看啊泰的零三。太史的灵山,我们看是什么?我叫的是哪一个呀?这个金额进行一个只拷贝是吧。哦,我这输出了,这还没看主函数啊。主函数怎么在前面打的呀?我看看啊,应该是这写了个text等于三这个地方等于Jack没有问题。
09:03
啊,这边呢,main.p点。PD,这个M在哪去了?他怎么前面打的呢。我后面还打印了一句话啊,我这还掉了一次,先把这个注销,我我怎么说,突然一下感觉好像见到了灵异事件呢,这个太零三这个地方肯定输出jackk,这个是没问题的。那么因为你是只拷贝,所以说你这地方改变呢,不会影响到外面这个P,所以说这个地方应该输出什么呢?这个输出汤姆,这个大家肯定能够理解,所以这输出是Jack,这输出汤姆这个大家肯定是能理解的,大家看。大家看这里是不是Jack,这边是汤姆是吧,但是但是有些同学这个地方他不能理解,说老师你这样调用不是传了一个地址过去吗。但是当你这样做完了过后,你会发现啊,你再次打印,你在这里面再次打印的时候,他仍然还是汤姆,因为这只是形式上传了一个地址,其实他在这种方式传递的时候,他这个P仍然是一个只拷贝,也就是说你即使通过这种方式去调用,你这里面改变了JK,对外面这个P仍然是不会起生生生效的啊,也就说这帮仍然是输字汤姆,能理解吗?
10:13
再说一遍啊,这个仍然是从形式上啊,从形式上看。是传了,是传入地址了,但是本质本质仍然。仍然是只拷贝。这呢,为什么只拷贝,因为你这个类型,这个地方类型系写的是纸类型,能理解了吧。好,也就是他这个东西从形式上看,那么编译器在做这个优化的时候,他仍然把它给给它改成这个形式。还是给你改成这个形式,但是呢,他从语法上又支持这种写法,你你看这个很容易搞混淆的啊,你看我再做一遍,你会发现那个们仍然输出的是汤姆。大家看到。是不是仍然是汤姆啊?这是第二个面包,汤姆能理解吧?好,这里大家一定要小心啊,这可是一个陷阱,使用陷阱很容易把你蒙进去的,同样反过来也是一样,如果我们这个地方注意听。
11:10
如果我们这个地方有个text的零四,那么我把它改成一个指针类型。我把它改成一个指针类型,它也可以通过指类型或者是地址来调用,这个方法同样就会发生真正的改变了啊,为了以示区别,我把它改成Mar,注意听讲。注意听,那这个时候我要去调这个跟指针类型绑定的,这个呢,大家看我这样调是可以的,首先按照正规的方法来调,应该是这样调P。点TEST04对吧,因为你你是指针嘛,所以说传一个地址进去,这是没没毛病的,好调完了过后呢,我们又在这边输出一句话。我们看这个时候改成什么了,告先告诉大家这个结论,但想因为你是按照这个标准方法去调用给他的,他又是指针,所以说你这个P点内呢,肯定把它改了。
12:05
那这个Mary就会直接影响到外面这个P对吧,所以这个地方应该输出Mary。我们看是不是这样子的,那当然这个地方也也应该输出Mary。也就是说,两个marry。注意看啊。大家看是不是两个Mary?对吧,一个MAR2个Mar,这个没问题吧,因为它是标准使用方式,而且它还支持这种写法,就是你直接p.tEST零式也可以。为什么呢?我在前面讲过这种写法呢,它等价。它等价于这种写法。因为底层的编译器给我们做了一个优化处理。对吧,那说说明你这样调呢,调的效果呢,跟上面一样的。也就是说你这种方式呢,他仍然会去修改到外面这个Mary啊,这个Mary这个地方改了也会修改到去改变它,因此我这里就总结了一句话,大家一定要注意听,对于普通的方法呢,如果他这个接收者只是直类型,那就只能传,如果是直类型。
13:08
就不能将指针类型传给他,反之亦然。但是如果你是第一个方法。定义这个方法接收者为值类型,你可以用指针类型去调用该方法,也可以用指类型反过来调。啊,但是最终决定权是在哪里呢?还是看你这个地方到底是指类型还是指质类型,再说一遍啊,最终这个到底是进行拷贝这个地址,还是整个这个只拷贝,还是取决于这个位置。到底这是直类型还是引用类型,这地方是关键,而不在于这个地方的形式,明白吧。好,我再我再说一遍啊,这个合适经常用来做面试题的理解了吗?但是但是为什么他这样子呢?就是其实当时的这个够让设计者他主要是为了方便,结果这样一设计过后呢,其实反而容易混淆这个概念。
14:00
其实很容易很容易蒙圈的,一般因为一般的人会,诶,你这不是按地址传了一个地址传给这个P吗?那你这个P就应该就应该是这个,这个P就应该指向外面啊,但是实际上他仍然还是只拷贝。明白这意思吧。OK,那同样这个道理也是一样啊,这个这个从形式上看是传入一个值,但是本质上传的就是地址。这句话我把它粘过来。再说一遍啊,这方很重要,从形式上好像传入的是是个纸拷贝,传入的是值。传入之类型。但,但本质上仍然是地质拷贝。为为什么它是地址拷贝呢?其关键的原因主要看TEST04里边它这个跟它绑定的这个类型是什么。好,我我说到这我就不再多说了啊。啊,大家一定要把这闹得很明白,不然的话,你以后肯定是要肯定是看不懂别人代码的。
15:03
因为有些人就是要去用哎p.tEST的,你是一下就蒙圈了。对不对,好,我把这个地方呢,给同学们整理一下好不好。大家好好体会一下啊,这讲的是方法和函数的区别。方法和函数的区别,我把它整理到这里。把这个笔记打开。方法和函数的区别,来给他一个标题三。区别,我一共给大家整理了有三点,对不对。前面两点呢,其实呃,这这一点调用方式不一样,这个呢我就不再多说了,这个比较简单。对吧,这个比较简单。好,那么第二点。第二点就是对于普通普通函数而言,诶,这个地方没有没有变化啊。把地方再整理一下,一什么不变了,不变算了,我去把它整理一下啊,对于普通函数而言,它是这样子的啊,就必须是对应的关系,就是接受着为值类型,就不能将指针类型数据传给他,反之也是一样的,那么我在这里举的有例子。
16:13
哪里举的例子这儿。对吧。是不是这样子的。就是。这样子的是吧,这样子的,我把它复制到我们的笔记里边去。对吧,那你如果是这样写的话呢,你在调用的时候,就必须这样调用呢,就必须按照他的这个类型来做相应的调用,比如说咱们这写的这种方式。啊,必须要类型匹配啊这样子的。OK。把它板熟一下。那如果说你是一个方法,你是一个方法,如果比如说是刷的方法,当然也可以是普通类型的方法,也可以比如说inegr这种方法,Inegr绑定方法,也也也也遵循这种规则啊,也遵循这种规则,那么我我呢把这个给大家整理到这里去。
17:10
好,嗯,我们又写了这两个。方法前面那个是函数,这是方法对不对。好,把它整理一下,板书到这里来。没问题,那调用的时候呢,形式如下。对。看在这,我们这几种形式都行。好,我把它给它整理一下板书。看这里啊,你看我们这是不是用了两种方式啊。P013,还有按照地址传一个地址形式啊,给他传调用TEST013,但是本质上仍是去拷贝。再看这。这种方式调用了test尼式,传的是一个地址,这种方式呢,看起来好像是把这个P这个值传过去了,但是呢,从本质上人事地址拷贝,所以说最终决定到底是子拷贝还是还是这个地址拷贝,主要是看这个函数是跟谁绑定的。
18:11
跟哪种类型绑定的是关键,明白。好,我把这个地方也拷贝到这里,我做一个整做一个总结啊,对上面做一个总结。对这一点做一个总结,总结一下,一句经典的话,总结就是。不管形式是什么样啊,不就说不管,就是说呃不管。不管形式调用形式是怎样子的调用。调用。形式如何?其真正作用的是啊,真正。真正决定。决定。是只拷贝。只拷贝还是。还是这个地址拷贝。地址。
19:02
地质拷贝。看什么呢?拷贝主要是看看哪个呢,看这个方法是跟哪种类型绑定的,就说这个方法,这个方法适合哪个类型绑定的。哪个类型?内心。绑定的。好关联的,如果如果是和这个子类型绑定的子类型。比如比如structure啊,比如说我们前面写的这种person对吧,这个这个大家都知道,它是直类型。给他这个绑定的。那么最终就是只靠背则。是自考币。如果是这样子的,如果是这样子的啊同学P新person,那么这个呢,就是什么呢,则是。那如果是和自考地啊,如果是和。
20:01
指针类型。指针。是真。类型绑定。啊,比如。比如是什么呢?这种类型的则是地质拷贝。好,这就是要说的啊,再再念一看啊,如果适合值类型,比如说这种这种绑定的则是指拷贝,如果适合指针类型,比如说P这种啊行person则是什么呢?地址拷贝也说主要关键作用还得看它是跟哪种类型绑定,你不用去看形式,到底它是通过这种方式调用,还是这种方式调用,还是上面那种方式调用,我的空中不管,我主要是看。他到底是跟哪种类型绑定的,就可以决定这个结果。好吧,所以说这个地方呢,就是我们讲的方法和函数的一个最大的区别,其实其他区别它就没有了。就方法和这个函数,它的区别本身就不大,因为它的调用机制几乎是一样的,对不对?而形式上呢,有些区别,另外呢,方法就是它是跟别人绑定的,而函数它并不跟一个类型绑定,它并不跟一个具体的类型绑定,因此你直接调用就可以了,但是方法因为它是跟一个类型绑定的,那就必须通过这个类型的一个变量来调用这个方法。
21:17
能理解吧,同时呢,他还有在接收这个参数的时候呢,呃,或调用或者是接收这个参数的时候呢,诶他还有好两几种形式要给他说清楚,好,那关于方法和函数区别呢,老师就给大家讲到这里,大家看理解了没有,好我一共总结了有三点。如果你去听别的老师讲课,你肯定这帮很容易听蒙圈的啊,我故意我专门把它总结的第一点,第二点,第三点就是单独把把它拎出来,让大家把这个点把它搞搞清楚,搞透。啊,不然的话,你肯定看到别人代码,你肯定会马上就会蒙圈,尤其是像这种用法看特别容易迷惑人,给你出个面试题几几乎就倒了。你看这个地址,然后那边一改,问你那边那个通过这个方法去修改这个P,这个外面P有没有修改,一般来说90%以上的人都会说修改的结果。
22:10
根本就没有修改,因为他本质仍是只拷贝好,那关于这点呢,老师就先聊这些好吧。
我来说两句