00:00
那么我现在讲到这儿呢?我相信同学们可能有点觉得不过瘾,说韩老师这个讲的反射好像也没干什么事。好像也没做什么大事似的,也没也没感觉到它有什么用处啊,好同学们,那现在呢,应该让大家体验一下反射的这个威力了啊,反射威力,呃,因为这个这个最佳时间的代码特别多哈,我这已经把这代码给他写好了,那么我一边写呢,一边带着大家看啊,我把这个代码拿出来一点写注释,那代码这个太特别多,不是写不下来,太太费时间了,就一行行写啊,这写这写写20分钟,写十来分钟太慢了,所以说我这已经写好了,然后呢,我们来看这个事情,第一件事情看清楚了啊。反射最佳时间一,使用反射便利结构体的字段,这就有意义了。调用结构体的方法,并获取结构体的标签值。在这个地方呢?其实就解释了我们怎么去获取到结构体的标签。
01:01
就是你们看我们在写结构体的时候,曾经写过那个什么节省冒号,它是怎么拿到的呀,就这里面就可以解释这个问题了,那么我们看这个这个地方啊,来各位朋友好,这边的案例呢,就相对综合一点,各位我先把它列到这里,叫最反射的最佳时间,就是应应真正的一个应用场景了。好,我先来给他一个标题二,注意听啊,同学们。那第一个最佳时间呢,就是使用反射来对结构体的字段,包括它的方法进行一个啊进行一个调度,好看看这个怎么做。好,这里面要去做这件事情啊,同学们,我们现在想完成反射便利结构体的字段。还想调用结构体的方法。还想获取结构体的标签,那么这些呢都需要我们知道,尤其是在调用结构体的方法的时候呢,需要介绍两个特别重要的这个相关的方法,一个呢叫做method,一个叫做空,我们来看看这两个方法啊,我们来看看这这两个方法,这两个方法呢,都是reflect value的这个类型的方法,Method是什么,我们打开看一下。
02:23
Method呢,它是这样子的啊,它可以通过这个reflect value。在地方填上这个I,就可以返回这一个反射的这个V所持有的结构体的第几个方法。啊,第几个方法,那么方法的时候呢,这个I是从零开始的,比如说。比如说你这个结构体有三个方法,那么第一个方法的下标就为零,第二个方法的下标就为一。第三个为二,这是第一点,第二点再看这里,那么。
03:03
这个call是什么意思呢?就是获取到这个方法以后呢,可以调用这个call来真正的调用,或者是去调用这个这个对应的这个方法。那么这个扣后面呢,可以传一个这个传一个切片,大家看这个切片的类型是什么。这个切片的类型是reflecting value,也就是说,说白了,它什么类型都可以往里面放,但是你必须是reflect value这个类型的切片往里面扔。因为你将来这个方法,这个方法你你你获取的方法可能有参数嘛,那这个时候呢,我们通过切片往里面扔好了,那有了这个知识点过后呢,同学们,那么我们就来看代码了啊,注意这两个方法是特别重要的啊,这个方法特别重要,来我把这段代码先给各位同学放到笔记里面去,然后呢,我们一起来看。啊,代码因为太多了,这个这个一行写下来太费时间了啊,因而且它本身技术含量也不太高,如果是算法的话呢,我会写这个,因为他一看就明白的东西啊,纯粹就是手工活。
04:09
那我就写到这啊,这个叫最佳实践吧,Play应用啊,Best最好的一个应用啊,叫最佳实践,然后呢,我们看第一个应用。OK,叫apply。零幺。零幺,然后我在这里建一个文件,注意看啊。好,各位同学请看代码,我把它粘过来,我们一一句句的看,哪地方看不懂,你可以随时问啊,把这个包包先打上。Package package主包。然后呢,我们需要import一些相关的相关的包包,首先form这个包肯定是要有的,还有一个reflect这个包肯定是要有的,这个不说了,这两个大包肯定跑不了,好,我们来看代码第一个。
05:01
一句一句的写啊,这里声明了,声明或者定义了都可以定义了一个结构体,就是monster的结构体。这大家应该能看懂吧,内蒙名字乘积性别这边是他的。标签。Tag标签,好,紧接着这个大家能看懂吧,我给这个monster绑定了一个print方法,或者关联的一个print方法,输出这个monster值,好,这是一个方法。这是一个方法干什么呢?就是输出或者显示这个S的具体的值,这个应该大家能看到第三个我还呃,这是第二个方法,第二个方法呢,我写了一个叫get some,让它呢可以返回两个数的和。这也是一个方法。这大家能看懂的地方。方法,返回两个两个数的。
06:00
两个。两个数的和没问题吧,好,同学们再看第三个方法,第三个方法呢,我写了一个S。我写了一个site这个方法。好,这个方法呢,可以接收四个值去给我们这个monster赋值。对吧,好,接送四个值给谁,就给这个monster赋值。好,这个也很简单,好再来看下面这个,先不看这啊,先不看这,先看我们的主函数,主函数这个能看懂吗。这个是我们非常熟悉的名字,黄鼠狼精。啊,应该听我课的同学知道我最喜欢黄鼠狼精啊啊。黄大仙,黄大仙有个叫黄皮子坟,那个就是那个那个不是那个恐怖片嘛,是吧,诶那个就不是恐怖片,那是什么,那个那个盗墓笔记那个那个好看吗。还行是吧,黄皮之分就是专门抓那个黄大仙的,那这个是干什么呢?这个我定义或者叫做创建了,创建了一个monster。
07:09
创建了一个monster的实例。这个大家应该能看懂,紧接着我干什么?我把这个monster传进,传给了这个函数。将这个monster的实例。传递给。传递给谁了呀,给这个T。Structure这个这个这个函数。好,各位同学看一下里面东西,来,我们一起去看啊,他做了什么事情?他做了什么事情,第一件这个大家能看懂吗?这个要看不懂是过去啊,哦一看哦,这个地方不就是拿到它的一个reflect,就是获取他的reflect,注意听啊,我要写到type这个类型。没问题吧,这个肯定能看懂,这个看不懂应该说不过去,这个是获取了什么呀,这个是获取到这个A传进来的,这个A对应的什么类型呢?它的一个这个。
08:11
Value类型,注意是value类型啊,不是这个是这个类型,好这个地方能看懂吗?是不是我通过这个value获取到它的类类别呀,A对的,我获取到类别能看懂吗?获取到A对应的类别。对比这个大家应该能看懂,那我这做了一件什么事情?KD如果不等于reflect structure。你觉得我想干什么事,是不是我看一下你是不是个结构体啊,如果不是结构体我就不玩了,因为我的案例是不是要去测试一个结构体啊,如果你都不是一个结构体,我还玩个啥呀?啊,就是说我这做了一个判断。判断,如果,如果传入的传入的不是结构体,我就不玩了。
09:00
就退了,就不玩了,就退出了,明白意思吧,这地方应该能看懂,就说我不玩了,因为我的我的目标大家看清楚了,我的目标是干什么事,我的目标是对一个结构体进行一个便利,你都不是结构体,我便利啥呀,我没法便利,我玩不了了,所以说呢,在反射里面这个地方就提示大家其实是可以进行这个类别判断的。因为刚才我打印出来KD就是类别是什么?类别是这个type,哎,你看这方它是有个KCA就是类别,你看这里面我们就看点进去再看它不就这些东西吗?但是这些东西啊,是在哪里定义的。可能有同学觉得,哎,老师你这不是波尔吗?注意啊,这个count是在这个K里面定义,在这个reflect包里面定义的,所以说你使用的时候应该是reflect,你在使用的时候应该是reflect这个包包下面点什么什么什么,比如说结构体就应该是它是这么来的啊,是这么来的,那么它比较的时候,其实就是一个常用的比较,是不是这个意思啊,就是个常用的比较,因为我拿到你那要相等嘛,所以它是它是数字,其实是可以比较大小的。
10:15
啊,所以说这就是为什么这帮我们可以进行一个比较,接着往下看。好,下面这句话能看懂什么吗?哪个同学可以告诉我?能告诉我这是干什么吗?哪位同学能告诉我?哎,是不是就获取到我一共有几个字段呀?哎,好了,这个就大家看懂了,获取到该结构体有几个字段?好,同学们跑一下,现在为了不让别的代码影响我们,我们先将下面的代码进行一个注销,看代码应该怎么看啊?将来你们以后看比较多的代码呢,你可以按照韩老师这个思路来玩,那这一注销哦,我先看看它到底是什么呀,来跑一个,他应该返回一个四。因为我现在呢,确实有四个四个变量来跑,一个CD,一点点CD到刚才我们讲的best应用,然后CD到我们第一个best应用。
11:10
啊啊BEST1好应用一,然后go run命点go跑起来,同学们看效果哦,真的是有问题啊,他他什么玩意儿,他说我没有用过这个是吧,啊没用,先展示,暂暂时不用,这个东西很重要哈,这个东西这个将来很重要,不要小看它,我先暂时不用它走人。好,同学们看效果哦,原来真的是有四个字段。有四个字段,那假如啊,假如说老师,假如你再加一个字段呢,比如说也可以,比如说我再加了一个字段,叫做这个地址吧,ADD res时寸。那如果你加了一个字段的话呢,已保存保存就看你这怎么赋值的了。哦,因为你是这种方式不负值,那个不给的话是个默认值是吧,所以说我这样一执行应该返回几啊,返回五,所以你看这个反射还是很强大,它马上就检示出来,你有五个字段能能理解哈,就一一点一点,这个感觉要出来了,好,那么我先把它撤回去,我把它撤回去接着往下看,那么现在先不说,我已经把所有的字段拿到了,下一步我遍历这个字段。
12:18
哦,便利是什么便利的,这有点意思了啊。便利。遍历结构体的所有字段怎么遍历的?I小于number I加,加的是第几个,值为多少?大家看这里。I是代表第几个字段?value.fail I,看这里,同学们。我用这个,大家知道这个value是什么吧,是不是reflect reflect value啊,它里面有个方法叫field,这个里面填一个I就代表返回了这个这个字段,那么这个字段是什么类型呢?同学们要看一下手册,它是一个字符串呢,还是又是一个类型?大家看它其实是调用的fair。
13:03
Value field,看看哦,它又返回这个value,那么这个value。理论上说啊,理论上说这个Y6,它反回的又是一个这个这个这个这个玩意儿了,但是你如果直接输出呢,我们刚才是不是还记不记得我们把一个反射好的一个VALUE61个整数打印出来,是不是它也把值给我们显示出来了,对吧?所以说这个地方呢,是可以把这个子平显示出来了,是多少就是多少,但是此时此刻大家一定要注意,你不能对它进行任何的运算,比如说你反过来是个整数,你是不能加减的,但是可以看一下。你你也可以把它转,转成一个相应的类型,这个是可以的,怎么转呢?可以,如果要写的更更好一点,你可以用个呃,那个Switch type,好,这个就把字打出来了,这个地方很重要,同学们。这个地方特别重要,这是干什么呀?获这个地方是获取是第几个字段,值是什么,这个是获取到它的标签。
14:02
那么获取它的标签这个字绝就不能用,注意听就不能用value了。不能用value,为什么这样说呢?好,我们先看看啊,它这里我用的是type,用value行不行,我看一下。用Y6。用value不行,为什么用value不行呢?注意这个type它也有个fair,但是刚才大家看到这个fair返回的是一个value。而这个type里面的是返回什么类型,这是很关键的点,打开它。大家看在type里边。在我们type这个里面有方法的,哪个方法,Type里面有一个方法叫做field的,看清楚了。哦,但人家返回的类型是field,跟刚才那个是不一样的咯。它是一个返回截fair,这里面有什么东西呢?1.1个好东西看出来了,哦,这个又是他们一个结构体。
15:07
这个结构体里面有一个叫T哦字段的标签,终于拿到了,看到没有,但是它是它的一个字段名,所以说你在这不需要方法,你就直接点就可以了,但是这个tag呢,你要把它的名字取出来,就说你要把它对应的值取出来,后面它有一个类型,它是不是的T呀,它是这个了,又不一样了,再点进去找。哦,这边有个可爱的get方法,里面写的是K。哦,这个K是什么?知道了吧,这个K真正才返回这个尺寸。那么这个KK是什么呢?这个K就是我们这个结构的标签里面写的这玩意。终于解释了那个为什么你的那个结构体反射可以拿到这个值了,因为它底层这个反射给你来玩的。
16:00
那我们可以想象到这个这个序反序列化,序列化里面它应该有一段类似的代码。这个,但是这个地方其实是可以变化的,只是序列化它应该写死了,所以说为什么我们在前面讲的时候,序列化的时候,你这个标签必须写节省,因为它底层写死了,其实这个地方是可以变的,但是返需的话,他已经给你写死了,他就叫接省,你就改不了,如果你自己定义,其实你是可以改的。你只要把这个名字改完就可以了,好,终于拿到了,拿到过后呢,我们要判断有没有值,因为有些字段有标签,有些字段没有标签,所以说我做了判断,我做了什么判断,如果。如果该字段,该字段有标签,有这个tag标签。标签就显示就显示,否则就就不显示了,就不显示。
17:00
好,同学们看看清楚了,现在我们跑一把看效果啊,同学们,这个大家应该能接受啊,接着看,跑起来。哦,这地方要要用到这个type了,注意再说一遍啊,这个type的fair和这个。这个这个这个reflect reflect value,这个field是不一样的啊,所以说这个地方用要标签一定用type,不不能用这个这个玩意啊好,所以说我把它打回去,打回去过后呢,我们再来看效果,同学们请看代码。现在呢,我们可以看到一个比较完美的一个结果。说第一个字段它的值是黄鼠狼经,第二个呢啊,第一个字段它还有对应个tag是内蒙第第一个字段就是其实是第二个字段,那它的值是400,然后它对应的标签的是这个第三,第二个就第三个字段呢,值是这么多啊,第三个是空第,就是B2和B3没有标签。如果你加一个马上就能编辑出来,比如说说韩老师,我这样加一个呢。
18:02
比如说同学们,假如我们在这个地方再加一个标签。说诶,我在这加一个我的标签叫杰森,比如说这个叫成绩。好,那么这个时候呢,他按照这个取的话,他应该能再建立一个新的标签出来,就是呃,成绩啊成绩我们看是不是这样子的,果果然拿到了,看到没有很很动态的,当然了说老师,如果我这个接生,我这线写错了呢,比如我写成HSSP了,那你这个就拿不到。因为他得的时候,他按这个K读的,你看如果你像这样一写啊,这个时候你会发现怎么样呢,他拿不到那个成绩了,因为名称不对,除非你把分改了。说说老师,我们我们改成这个自己的改成HP了,你改成这个,那你那你另外两个拿不到啊,好,这个大家知道是什么意思就可以了,好我还是把它改回去。改回去啊,改回去OK,大家明白这个道理,好,这个呢,就演示了怎么去拿它的字段,以及它的值,还有它的这个什么呀,呃,它的这个标签的名称,OK。
19:05
好好接着往下看,接着往下看,下一个就是方法了,我们刚才把变量结构体的啊,就结构体的字段这些玩了一把,那么下面就是方法来看代码,这个我相信同学们能看懂,这这个案例讲完了过后,下面的案例就是比较简单了啊,这个方法是获取到有多少个方法。获取到该。该这个变量对应该结构体吧,结构体有多少个方法,那用的是VALUE6点number method,您可以看一下这个Y6是可以拿到的啊,然后一共有几个方法呢?我们一共写了有。一个两个三个方法应该返回三。应该返回上走代码。对面可以看到我一共有三个方法,果然如此。三个好,下面的任务就是我要用反射调方法了啊,看代码这个很重要,这个将来有可能你们在写高级。
20:06
高级项目的很有可能用到这个东西啊,那现在我们看看怎么调方法,大家看这代码。看代码啊。各位,我。这个地方。大家看这题,大家能看懂什么意思吗?VALUE6点MESSAGE1是不是我获取到第二个这句话的?有同学能给我解思吗?是不是我获取到它的第二个方法呀?我获取到它第二个方法,哎,第二个方法我在调查的时候,我一个参数都没有填。这个是第前面这一部分。注意听啊,前面这一部分是代表获取到它的第二个方法,空代表调用该方法,这个你可以分开写。也可以合在一起写,我合在一起写的,那同学们应该感觉到很奇怪,说老师你,你这是会学的第几个方法,我获取到第二个方法。
21:02
获取到第二个方法没问题,那我获取到第二个方法,我还调用了它,调用它。那大家感觉好好怪啊,韩老师你是不是写错了吧?第二个方法按理说不是这个吗?这是第一个方法,这第二个方法,那第二个方法你这要传两个参数,你怎么一个都不传啊。诶,这有问题了,但实际上当我语音行的时候,你会发现它掉的是这个方法,好,这就涉及到一个很重要的一个原则,大家看啊,我给大家跑一下。你看我调的是这个方法,我先把下面的代码先给他注销一下。大家看这里。我调用是哪个方法呢?我用反射把那个打印出来了,看诶看到我调的反而是第一个方法。很奇怪,你看黄鼠狼精430.8我都做出来了,哎,那有点意思了,那你按理说你掉第二个方法是他才对呀,好告诉大家一个原则啊,同学们,那么这里面有有一个原则是这样子的,同学们,它在进行这个排序方法排序的时候,它是按照函数的名字进行排序。
22:18
怎么个意思,就是说先比较它的阿斯克玛,大家看第一个字母是P,这个是。G。那么大家想一想,第三个是S,按照这个字母排序,哪一个排第一个呀,G是不是排第一个,然后P排第二个,第三个是不是S,所以说这个才是第一个方法,这是第二个方法,这是第三个方法,这么来的。当然有同学说了,说老师。你有没有,你有没有一种反射,有没有一种方法是根据它的函数名来反反射它的呢?理论上说是有,但是如果你都知道函数名呢,你还反射啥呀?
23:03
你都已经知道你家有一个函数名,除非你这样子的啊,你把先把函数名的先编辑出来,然后通过这个调用,其实本质没什么区别。本质没什么区别,那么同学们可以看到,如果大家看到啊,我把这个改一下,我把这个东西拿到最下面来,我及时把这个P放在这个,最后你发现调用的还是它,就它跟这个顺序没有关系,注意听啊,跟这个顺序没有关系,待会儿我们强调一下,你看我加了一个波浪号,我再去运行,你看效果同学们。哦,你看还是打印的是它,所以说我把这做一个重要的注释啊,重要的注释很重要就是这个函数的就是方法的,方法的排序是默认,默认是按照按照什么呢?按照函数名,函数名的排序按照什么规矩呢?按照阿斯科玛的这个这个这个这个比较啊阿斯柯玛的。
24:04
别人这个问道,你要达成了啊,阿斯克玛的一个一个大小排序,好,这个写完了,那么我这调的是什么呢?调的是没有。参数的,但实际上大家看到我这里还有两个方法,一个是get上,一个是said,它是需要传参数的,那同学们可以看到这是怎么做,打开我们手册,我们发现它的空这个方法。就是它首先是获取到method。他获取到这个method。啊,大家看这里面它有获取的这个message集啊,往这看M打头,M打头的在这啊,它这个M法打出,它是相当于说把这个函数给你返回来了,返回来过后呢,大家看这还有message by name也行啊,它可以通这个名字来看,那么这个时候呢,调这个call的时候,大家看把这个扣打开打开。这个message它因为它反馈还是个value嘛,所以它还能反回来再调它的方法叫call。
25:04
好,上面有一个方法非常重要啊。呃,在哪里去了,在这儿。这手册就是在这有点麻烦,就是啊在这看正排序很诡异,他这个怎么看啊,同学们看这里。它掉的时候呢,要传一个这个Y6的切片。谁的谁的value是reflect reflect.value这这个东西的一个切片,那么这个切片呢?这个是in代表输入最后返回的又是这个切片啊,还是reflect value切片。因为对他来说,注意大家可能这听着有点晕,说好老师,我觉得有点奇怪,你怎么传的也是这个类型,反射的还是一个类型呢?这就是反射的一个特点,反射它其实主要是靠这个value来玩的。所以说他返回来这个类型传的类型都是一样,但是呢,但是你你这个没有关系,就是说他是用这一个类型把它都囊括完了。好,所以说你看这里我在调的时候应该怎么调呢?大家看我,我这里写的非常的简单啊,大家看非也很清晰,大家看我把它打开。
26:08
我先搞了一个flex的切片。我先声明了一个。声明。声明了一个,这个切片大家应该能看懂。然后呢,我就往里面放直了,因为它是切片嘛,所以判是可以跑的,那这个怎么做了一个这个东西呢?Reflect value,诶大家看到没有,我把一个常量时,是不是转成了一个reflect value,这个这个值啊,再加了一个解,又把这个加进去了,所以说在反射这个调用过程中,其实它是以这个reflect value来进行处理的,自动算也是一样。好,把它放进去,最后看我如何调用,还是跟上面一样。也是Vr.ma的零,零代表是第一个,第一个它是求两个数的和,所以说我把这两个数放进去,那么最后这个调用完了过后这个res,注意这个这个res又是个切片。
27:07
是个什么切片啊,它传入的是这个切片,它返回的还是这个切片类型啊,返回的还是这个切片。返回的返回的还是一个区别,你你要取的时候,你一定要知道你返回几个结果啊,那当然按顺序来了。那我知道R1是零。就是因为它返回一个和嘛,只有一个,就I是零,就是第一个切片,它其实只返回了一个,这个切片的大小其实也只有一个,你们可以可以认识一下,这个应该是一,那取出它第一个点int,因为我知道返回的是int,首先这取的如果如果说你不确定这地方应该还要加一个断言。啊,其实你不要这个也可以,如果你不要这个的话呢,它也打印出50,但是类型不一样。如果你你这样写它也打印出物是只是类型不一样啊,所以说我这样直接就把它值取出来了。
28:02
OK,好,代码咱们就分析完毕了,郭同学跑一下吧。好,请看代码完全正确,好同学们,我们花一点时间来简单交流一下啊,因为这个讲完了,这个我我虽然没有一步一步写出来,但是我相信还是讲的比较细的,这个讲完了过后,大家呢,应该就是有点感觉,就是一个有有点通了,就是说我们这个结构体,就是说我可以通过反思可以玩什么东西呢?我可以我可以你看啊。如果对一个人来讲,就说我创建了一个实例,然后我调用一个方法,结果这个。结果这里面的东西都被调用起来了,你应该感觉到很神奇才对。因为按照我们前面讲的所有,就是我们从第一天开始讲构语言,老师就告诉你们,我们怎么去调一个结构的方法呢?是创建一个结构的词义,然后调用的方法,永远这样说的,现在你突然变成什么,你只需要创建一个词,传给一个方法,用反射就可以帮你做所有的事情。
29:06
那相对说将来你如果是做的这个底层的框架,那你就是把这个东西你放进去就可以,他该干什么就干什么了。比如说一个最经典的案例,比如说像那个像像有些数据,有些框架,他要求你那个控制器必须以什么什么打头,比如说index什么什么打头的。那么我在反射底层,我就可以去找你的这个对应的这个入函数,然后帮你调。这就是一种框架,它就起来了,因为我可以告诉你,你,你将来对应的这个这个这个这个控制器是什么,然后你的函数名必须以什么打头,你看很多框架是有规范的,为什么很多框架它会告诉你,你在写一个控制器或者写猫的时候,这个函数的命名方式必须怎么怎么样,而不能怎么怎么样。对不对?你看刚才我们讲的那个testing,大家回忆一下啊,同学们,我们在前面应该是昨天我们讲的一个testing框架,是不是我曾经讲过它的那个用力必须是TST打通。
30:15
这就说明test底层也一定用到了反射。你看你这个方式为什么调,他帮你吊起来了是吧,他就有可能去去扫描,然后帮你帮你加进去哦一看哦,就你吊起来,如果他发现你规范不一样,他可能就调不起来了。好,所以说是这样一个底层的一个关系,好了同学们,那关于第一个应用呢,我们先讲到这里,我们对它进行一个板书啊,进行一个板书,好板书一下,呃,具体的代码呢,给各位朋友放在这个地方,包括我的注释。包括我的注释。包括我的注释。好的,各位同学,那第一个这个呢,我讲的比较细,后面这个呢,我想这样说啊,今天后面还有几个案例,我先简单说一下,晚上。
31:02
你们先看一遍,看不懂明天再问。还有布置的一个作业,好,我先截取一段小视频。
我来说两句