1.剖析a.out是汇编汇编如何生成运行
2.码上去学:C++从入门到进阶的系列书籍推荐!
3.C++è¦å¦äºä»ä¹
4.C++从入门到进阶的源码源码系列书籍推荐
5.Golang源码剖析panic与recover,看不懂你打我好了
6.Go interface 原理剖析--类型转换
剖析a.out是剖析剖析如何生成运行
编译过程从源代码开始,经历预处理、汇编汇编编译、源码源码汇编和链接四个阶段,剖析剖析财源码最终生成可执行文件a.out。汇编汇编首先,源码源码预处理阶段对源代码进行处理,剖析剖析包括展开宏定义、汇编汇编处理条件编译指令、源码源码展开#include指令、剖析剖析删除注释、汇编汇编添加行号和文件名等。源码源码此阶段保留#pragma编译指令。剖析剖析
进入编译阶段,源代码被转换为一系列记号,通过词法分析、语法分析、语义分析和源代码优化,生成目标代码。词法分析将代码分解为记号,如关键字、标识符、字面量、特殊符号等,并放入符号表与文字表。语法分析构建语法树,实现对表达式的语法层面分析。语义分析则为语法树中的表达式分配类型,确保类型匹配,并进行隐式转换。源代码优化可能在这一阶段进行,如将表达式简化。例如,原本的代码 "int a = (a+3)*(2+5);" 可能被优化为 "int a = (a+3)*(7);"
汇编阶段将编译生成的目标代码转换为机器指令,即汇编代码。此阶段是将高级语言代码转换为计算机可直接执行的指令。
链接阶段负责对生成的汇编代码进行整合。主要包含三个部分:地址和空间分配,解决符号引用,以及进行重定位。此阶段确保所有模块能正确引用其他模块的代码和数据,同时处理动态链接库的引用,最终生成可执行文件a.out。
码上去学:C++从入门到进阶的系列书籍推荐!
要多读书,读好书!在学习编程的过程中,反复阅读书籍能带来新的收获,尤其在工作年限和经验积累之后,对内容的理解会更加深刻。下面将为您推荐C++从入门到进阶需要阅读的图片系统源码一些经典书籍。
首先,C++的入门阶段,需要打好C语言的基础。
1.1《C语言程序设计》(谭浩强著):这本书是学习C语言程序设计的优秀教材,被全国大多数高校选用,是学习C语言的主流用书。内容通俗易懂,是初学者的必备书籍。在排查编译问题时,翻阅相关章节,精准的文字表述让人豁然开朗,很多学生时代难以理解的内容,在工作后有了更深刻的理解。
1.2《C++ Primer 中文版(第5版)》:这是学习C++语言最经典的入门教材,详细讲解了C++语言的基础语法和概念。最新第5版全面采用C++标准,体现了C++语言的重大进展。丰富的教学辅助内容、醒目的知识点提示以及精心组织的编程示范,使得本书在C++领域权威性更加强大。无论是初学者还是中高级程序员,本书都是首选。
接下来,学习C++应用开发阶段,可以关注以下书籍。
2.1《VC++深入详解》(孙鑫著):本书是学习Windows编程的入门经典教材,从实际应用出发,深入浅出地讲述Windows程序内部运行机制、MFC框架、文本、菜单、对话框、文件操作、网络编程、进程间通信、ActiveX控件、动态链接库、HOOK编程等多个主题。
2.2《深入浅出MFC》(侯捷著):本书是学习MFC编程的经典教材,分为四大篇。从学习MFC程序设计的基础知识到掌握Visual C++开发环境,再到深入理解MFC框架的骨干程序,最后以微软公司提供的范例程序Scribble为主线,深入讲解Runtime Type Information (RTTI)、Dynamic Creation、Persistence (Serialization)、message Mapping、Command Routing等核心技术。
随后,C++的进阶阶段,推荐以下书籍。
3.1《Effective C++:改善程序与设计的外卖跑腿源码个具体做法》(Scott Meyers著):本书被誉为C++程序员的必读书籍,世界顶级C++大师Scott Meyers的成名之作,读过此书将极大提升C++编程功力。
3.2《More Effective C++:个改善编程与设计的有效方法》:这是Scott Meyers的Effective系列书籍之一,是Effective C++的进阶版本,深入理解C++编译器如何解释代码,才能写出健壮的软件。
3.3《STL源码剖析》(侯捷著):本书详细讲解了STL在各种C++项目中的应用,深入剖析了vector、list、heap、deque、Red Black tree、hash table、set/map的实现,以及各种算法(排序、查找、排列组合、数据移动与复制技术)的实现。
此外,掌握Windows编程,推荐以下书籍。
4.1《Win多线程程序设计》(Jim Beveridge/Robert Wiener著):本书详细讲解了Windows系统中的多线程编程技术,分为三篇,涵盖线程的启动、结束、核心对象、同步机制等。
4.2《Windows核心编程》(Jeffrey Richter/christophe Nasarre著):本书是Windows核心编程的经典指南,深入理解Windows特性,适合Windows开发人员使用,全面修订第5版针对Windows XP、Vista和Server 进行了内容更新。
对于Linux系统学习,推荐以下书籍。
5.1《鸟哥的Unix私房菜》:本书是Linux入门书籍,系统地介绍了Unix系统起源、文件系统、命令、Shell脚本、系统安全、系统特性等内容,适合初学者。
5.2《Linux内核源代码情景分析》:本书采用情景会话教学方法,全面深入剖析Linux核心源代码,对Linux的独特优点和改进点进行评述。
在汇编与软件调试方面,推荐以下书籍。
6.1《汇编语言》(王爽著):本书是汇编语言学习者的必备宝典,采用全新结构组织内容,深入讲解汇编语言的关键环节。
6.2《IDA Pro权威指南》(Chris Eagle著):本书介绍了应用广泛的静态反汇编工具IDA Pro的使用方法,给出大量图例和C代码实例,骰子竞猜源码帮助读者掌握TCP/IP的实现。
在设计模式、数据结构与算法方面,推荐以下书籍。
8.1《boost程序库完全开发指南》(罗剑锋著):本书全面介绍了boost库的用法及其在实际开发中的应用。
8.2《大话设计模式》(程杰著):这本书通过趣味问答方式讲解设计模式,让初学者更容易理解设计原则和设计过程。
8.3《设计模式:可复用面向对象软件的基础》(Erich Gamma/Richard Helm/Ralph Johnson著):本书精选出个设计模式,总结面向对象设计的经验,并以简洁可复用的形式表达出来。
8.4《数据结构与算法分析》(Mark Allen Weiss著):本书是学习数据结构和算法的经典著作,通过C程序实现,强化了对抽象数据类型概念的理解。
8.5《算法导论》(Thomas H. Cormen著):本书全面讨论各类算法,注重严谨性和全面性,适合不同层次的读者学习。
以上书籍覆盖了从C++入门到进阶的各个阶段,无论你是初学者还是有一定经验的开发人员,都能从中找到适合自己的学习资料。希望这份推荐能帮助你进一步提升编程技能,欢迎持续关注码上去学!
C++è¦å¦äºä»ä¹
å¾å¤æåæ³ç¥éC++è¦å¦äºä»ä¹ï¼ä¸é¢å°±è®©æ们æ¥ççå§ã
é¦å è¿æ¬ãCç¨åºè®¾è®¡è¯è¨ãæ¯å¿ å¤çå ¥é¨ä¹¦ï¼åéè¿å¦ä¹ ãCé·é±ä¸ç¼ºé·ãããC++ Primerãè¿ä¸¤æ¬ç»å ¸çå¦C++ç书æ¥ç¨³åºåºç¡ç¥è¯ï¼ç¶åå¦ä¹ C++ãEffective C++ãè¿æ¬ä¹¦æ¥æé«æçï¼STLæ¯C++çç²¾é«ï¼æ以å¦å¥½STLæ¯å¿ é¡»çï¼æ¨èãSTLæºä»£ç åæãï¼å¦å®åºç¡ç¥è¯å°±å¦æä½ç³»ç»ï¼ç»å ¸çæä½ç³»ç»ä¹¦ç±æãæ·±å ¥ç解计ç®æºç³»ç»ãï¼é¤äºè¿äºè¿å¿ é¡»å¦è®¡ç®æºç½ç»åLinuxç³»ç»ã
C++è¯è¨
C++ï¼æ¯å½é æ åçç¼ç¨è¯è¨ï¼æ¯è¿ç¨é常广æ³çä¸ç§è®¡ç®æºç¼ç¨è¯è¨ï¼æ¥æå¤ç§çç¨åºè®¾è®¡é£æ ¼ï¼å¦ï¼è¿ç¨åç¨åºè®¾è®¡ãæ°æ®æ½è±¡ãé¢å对象ç¨åºè®¾è®¡ãå¶ä½å¾æ çï¼æ¯éç¨çå¤éç¼ç¨èå¼ç¨åºè®¾è®¡è¯è¨ã
C++å ¥é¨
é¦å ææ¸ æ¥C++çä½ç¨ååC++çç®çï¼ç¶åå¼å§ç¬¬ä¸é¶æ®µå¦ä¹ C++çåºç¡ç¥è¯ï¼è¡¨è¾¾å¼ãæ°ç»ãè¿ç®ç¬¦çè¿äºé½æ¯C++çåºç¡è®¤ç¥ï¼ç»æä½ãä½è¿ç®ãé¢å¤ççæ¯å¯¹åºç¡ç¥è¯çæ©å±ï¼åç»è¿ä¼å¦ä¹ å°VC++ãCãTCçï¼äºè§£åå¦ä¹ äºç论ç¥è¯ä»¥åå°±å¯ä»¥å°å¦ä¹ å°çç论ç¥è¯é½è¿ç¨å°å®è·µä¸å»ã
C++çä½ç¨
C++æ¯ä¸ä¸ªä½ç¨äºè®¡ç®æºç¼ç¨ä¸çé«çº§è¯è¨ï¼ä¸»è¦ç¨éæ¯ç¨æ¥ç¼åç³»ç»è½¯ä»¶ååºç¨è½¯ä»¶ï¼æ¯ä¸ä¸ªä½ç¨äºè®¡ç®æºç¼ç¨ä¸çé«çº§è¯è¨ï¼æ¯å¤äºé«çº§è¯è¨åæ±ç¼è¯è¨å½ä¸çä¸ç§è®°è¿°æ§è¯è¨ï¼æ¯è¾é è¿ç¡¬ä»¶åç³»ç»ï¼å®ä¸ä» å¯ä»¥é¢å硬件åç³»ç»ï¼ä¹å¯ä»¥åæ±ç¼è¯è¨ä¸æ ·ç´æ¥è®¿é®ç¡¬ä»¶åè½åé«çº§è¯è¨é¢å广大ç¨æ·ï¼C++ççæ代ç çä¹æ¯å ¶å®é«çº§è¯è¨è¦é«ï¼æ¯é»å®¢çå¿ å¤è¯è¨ï¼å 为æ¥è¿èªç¶è¯è¨ï¼æ以深åç¼ç¨äººååç±ï¼å®¹æè®°å¿ï¼åæ¶ä¾¿äºé 读å书åï¼ä¹éç¨äºæå¦ã
C++从入门到进阶的系列书籍推荐
要多读书,读好书!学习任何技能,阅读经典书籍都是不可或缺的一步。C++从入门到进阶,需要扎实的基础和深入的理解。接下来,我们将推荐一系列从入门到进阶的C++经典书籍,帮助您全面提升编程技能。1. C++入门书籍
了解C++之前,首先需要掌握C语言的基础。以下两本书是学习C语言的经典教材。1.1 C语言程序设计(谭浩强)
本书被广泛采用为学习C语言的教材,通俗易懂,是初学者的必备读物。我在解决编译问题时,翻阅了该书的相关章节,精准的表述让我恍然大悟,很多学生时代未理解的内容,有了工作经验后,豁然开朗。1.2 C++ Primer 中文版(第5版)
这是一本学习C++语言的经典入门教材,详细讲解了C++语言的基础语法和概念。最新版全面采用C++标准,体现了C++语言的重大进展。丰富的教学辅助内容、醒目的知识点提示和精心组织的编程示范,使得本书在C++领域内权威地位稳固。2. VC++/MFC书籍
在掌握C++基础后,可以从简单的Windows编程开始,逐步熟悉Visual Studio开发工具的python源码大全使用。MFC虽然在大型商用项目中已较少使用,但它作为经典UI框架,对编写小型工具软件依然有重要作用。2.1 VC++深入详解(孙鑫)
这是一本学习Windows编程的入门经典教材,由浅入深地讲述Windows程序的内部运行机制、MFC框架、文本、菜单、对话框、文件操作、网络编程等多个主题。2.2 深入浅出MFC(侯捷)
本书深入学习MFC编程,分为四大篇,从学习MFC程序设计的基础到Visual C++开发环境,再到MFC核心程序,最后通过微软附带的Scribble程序实例,深入讲解Runtime Type Information、Dynamic Creation、Persistence、message Mapping、Command Routing等核心技术。3. C++进阶书籍
在具备一定开发经验后,需要深入理解C++特性,提高编写C++代码的效率和稳定性。3.1 Effective C++:改善程序与设计的个具体做法(第3版)(Scott Meyers著)
Scott Meyers的成名之作,是提升C++功力的绝佳契机。阅读这本书后,您的C++技能将显著提升。3.2 More Effective C++:个改善编程与设计的有效方法(Scott Meyers著)
本书是Scott Meyers Effective系列的进阶版本,深入解析C++编译器如何解释代码,助您编写出更健壮的软件。3.3 STL源码剖析(侯捷)
深入了解STL的内部实现,本书详细讲解了vector、list、heap、deque、Red Black tree、hash table等数据结构的实现,让您掌握各种算法的实现。4. Windows编程书籍
从事Windows应用程序开发的人,以下两本书是经典的选择,深入了解Windows系统特性。4.1 Win多线程程序设计(Jim Beveridge / Robert Wiener)
全书详细讲解Windows系统中的多线程编程技术,包括线程的启动和结束、核心对象、同步机制及其用途。4.2 Windows核心编程(Jeffrey Richter / christophe Nasarre)
本书是深入理解Windows特性的必备参考书,全面讲解Windows核心编程,引领数万程序员步入Windows开发领域。5. Linux书籍
Linux系统广泛应用于各种服务器,作为C++开发人员,学习Linux知识与技能至关重要。5.1 鸟哥的Unux私房菜
本书全面介绍了Linux系统的基本原理,适合初学者入门。5.2 Linux内核源代码情景分析
本书采用情景会话教学法,全面剖析Linux内核源代码,深入理解Linux系统特性。6. 汇编与软件调试书籍
掌握一定的汇编语言基础和软件调试技能,对于解决C++程序问题至关重要。6.1 汇编语言(王爽)
本书系统讲解汇编语言,为初学者提供循序渐进的学习路径。6.2 IDA Pro权威指南(Chris Eagle)
IDA Pro是应用广泛的静态反汇编工具,本书深入讲解其使用方法。6.3 软件调试(张银奎)
本书全面展示软件调试技术,是深入理解软件和自由驾驭软件的宝贵资料。6.4 格蠹汇编:软件调试案例集锦
本书通过具体案例解析软件调试,适合程序员和信息安全研究者阅读。7. 网络及TCP/IP协议
学习网络知识,掌握排查网络问题的方法是C++程序开发人员的必备技能。7.1 计算机网络(谢希仁)
本书系统介绍了计算机网络的基本原理和各种网络技术。7.2 TCP/IP详解(卷1、卷2、卷3)
本书从协议、实现和TCP事务协议等多个角度深入讲解TCP/IP协议。8. 设计模式、数据结构与算法
掌握设计模式、数据结构和算法是提高编程能力的关键。8.1 boost程序库完全开发指南(罗剑锋)
本书详细介绍boost库,帮助读者迅速掌握其用法和实际开发应用。8.2 大话设计模式(程杰)
本书以问答形式讲解设计模式,引导初学者理解设计背后的智慧。8.3 设计模式:可复用面向对象软件的基础(Erich Gamma / Richard Helm / Ralph Johnson)
本书精选个设计模式,总结面向对象设计中最有价值的经验。8.4 数据结构与算法分析(Mark Allen Weiss)
本书被世界众多大学用作教材,深入讨论算法和数据结构。8.5 算法导论(Thomas H. Cormen)
本书涵盖各类算法,旨在使不同层次的读者都能理解和接受。 通过阅读这些经典书籍,您将从C++的入门到进阶,全面提升编程技能,成为更加优秀的C++开发者。Golang源码剖析panic与recover,看不懂你打我好了
哈喽,大家好,我是asong,今天与大家来聊一聊go语言中的"throw、try.....catch{ }"。如果你之前是一名java程序员,我相信你一定吐槽过go语言错误处理方式,但是这篇文章不是来讨论好坏的,我们本文的重点是带着大家看一看panic与recover是如何实现的。上一文我们讲解了defer是如何实现的,但是没有讲解与defer紧密相连的recover,想搞懂panic与recover的实现也没那么简单,就放到这一篇来讲解了。废话不多说,直接开整。
Go 语言中panic 关键字主要用于主动抛出异常,类似 java 等语言中的 throw 关键字。panic 能够改变程序的控制流,调用 panic 后会立刻停止执行当前函数的剩余代码,并在当前 Goroutine 中递归执行调用方的 defer;
Go 语言中recover 关键字主要用于捕获异常,让程序回到正常状态,类似 java 等语言中的 try ... catch 。recover 可以中止 panic 造成的程序崩溃。它是一个只能在 defer 中发挥作用的函数,在其他作用域中调用不会发挥作用;
recover只能在defer中使用这个在标准库的注释中已经写明白了,我们可以看一下:
这里有一个要注意的点就是recover必须要要在defer函数中使用,否则无法阻止panic。最好的验证方法是先写两个例子:
运行我们会发现example2()方法的panic是没有被recover住的,导致整个程序直接crash了。这里大家肯定会有疑问,为什么直接写recover()就不能阻止panic了呢。我们在 详解defer实现机制(附上三道面试题,我不信你们都能做对)讲解了defer实现原理,一个重要的知识点**defer将语句放入到栈中时,也会将相关的值拷贝同时入栈。**所以defer recover()这种写法在放入defer栈中时就已经被执行过了,panic是发生在之后,所以根本无法阻止住panic。
通过运行结果可以看出panic不会影响defer函数的使用,所以他是安全的。
这里我开了两个协程,一个协程会发生panic,导致程序崩溃,但是只会执行自己所在Goroutine的延迟函数,所以正好验证了多个 Goroutine 之间没有太多的关联,一个 Goroutine 在 panic 时也不应该执行其他 Goroutine 的延迟函数。
其实我们在实际项目开发中,经常会遇到panic问题, Go 的 runtime 代码中很多地方都调用了 panic 函数,对于不了解 Go 底层实现的新人来说,这无疑是挖了一堆深坑。我们在实际生产环境中总会出现panic,但是我们的程序仍能正常运行,这是因为我们的框架已经做了recover,他已经为我们兜住底,比如gin,我们看一看他是怎么做的。
我们先来写个简单的代码,看看他的汇编调用:执行go tool compile -N -l -S main.go就可以看到对应的汇编码了,我们截取部分片段分析:
上面重点部分就是画红线的三处,第一步调用runtime.deferprocStack创建defer对象,这一步大家可能会有疑惑,我上一文忘记讲个这个了,这里先简单概括一下,defer总共有三种模型,编译一个函数里只会有一种defer模式。在讲defer实现机制时,我们一起看过defer的结构,其中有一个字段就是_panic,是触发defer的作用,我们来看看的panic的结构:
简单介绍一下上面的字段:
上面的pc、sp、goexit我们单独讲一下,runtime包中有一个Goexit方法,Goext能够终止调用它的goroutine,其他的goroutine是不受影响的,goexit也会在终止goroutine之前运行所有延迟调用函数,Goexit不是一个panic,所以这些延迟函数中的任何recover调用都将返回nil。如果我们在主函数中调用了Goexit会终止该goroutine但不会返回func main。由于func main没有返回,因此程序将继续执行其他gorountine,直到所有其他goroutine退出,程序才会crash。
下面就开始我们的重点吧~。
在讲defer实现机制时,我们一起看过defer的结构,其中有一个字段就是_panic,是触发defer的作用,我们来看看的panic的结构:简单介绍一下上面的字段:上面的pc、sp、goexit我们单独讲一下,runtime包中有一个Goexit方法,Goext能够终止调用它的goroutine,其他的goroutine是不受影响的,goexit也会在终止goroutine之前运行所有延迟调用函数,Goexit不是一个panic,所以这些延迟函数中的任何recover调用都将返回nil。如果我们在主函数中调用了Goexit会终止该goroutine但不会返回func main。由于func main没有返回,因此程序将继续执行其他gorountine,直到所有其他goroutine退出,程序才会crash。写个简单的例子:运行上面的例子你就会发现,即使在主goroutine中调用了runtime.Goexit,其他goroutine是没有任何影响的。所以结构中的pc、sp、goexit三个字段都是为了修复runtime.Goexit,这三个字段就是为了保证该函数的一定会生效,因为如果在defer中发生panic,那么goexit函数就会被取消,所以才有了这三个字段做保护。看这个例子:
英语好的可以看一看这个: github.com/golang/go/is...,这就是上面的一个例子,这里就不过多解释了,了解就好。
接下来我们再来看一看gopanic方法。
gopanic的代码有点长,我们一点一点来分析:
根据不同的类型判断当前发生panic错误,这里没什么多说的,接着往下看。
上面的代码都是截段,这些部分都是为了判断当前defer是否可以使用开发编码模式,具体怎么操作的就不展开了。
在第三部分进行defer内联优化选择时会执行调用延迟函数(reflectcall就是这个作用),也就是会调用runtime.gorecover把recoverd = true,具体这个函数的操作留在下面讲,因为runtime.gorecover函数并不包含恢复程序的逻辑,程序的恢复是在gopanic中执行的。先看一下代码:
这段代码有点长,主要就是分为两部分:
第一部分主要是这个判断if gp._panic != nil && gp._panic.goexit && gp._panic.aborted { ... },正常recover是会绕过Goexit的,所以为了解决这个,添加了这个判断,这样就可以保证Goexit也会被recover住,这里是通过从runtime._panic中取出了程序计数器pc和栈指针sp并且调用runtime.recovery函数触发goroutine的调度,调度之前会准备好 sp、pc 以及函数的返回值。
第二部分主要是做panic的recover,这也与上面的流程基本差不多,他是从runtime._defer中取出了程序计数器pc和栈指针sp并调用recovery函数触发Goroutine,跳转到recovery函数是通过runtime.call进行的,我们看一下其源码(src/runtime/asm_amd.s 行):
因为go语言中的runtime环境是有自己的堆栈和goroutine,recovery函数也是在runtime环境执行的,所以要调度到m->g0来执行recovery函数,我们在看一下recovery函数:
在recovery 函数中,利用 g 中的两个状态码回溯栈指针 sp 并恢复程序计数器 pc 到调度器中,并调用 gogo 重新调度 g , goroutine 继续执行,recovery在调度过程中会将函数的返回值设置为1。这个有什么作用呢? 在deferproc函数中找到了答案:
当延迟函数中recover了一个panic时,就会返回1,当 runtime.deferproc 函数的返回值是 1 时,编译器生成的代码会直接跳转到调用方函数返回之前并执行 runtime.deferreturn,跳转到runtime.deferturn函数之后,程序就已经从panic恢复了正常的逻辑。
在这里runtime.fatalpanic实现了无法被恢复的程序崩溃,它在中止程序之前会通过 runtime.printpanics 打印出全部的 panic 消息以及调用时传入的参数。
这就是这个逻辑流程,累死我了。。。。
结尾给大家发一个小福利,哈哈,这个福利就是如果避免出现panic,要注意这些:这几个是比较典型的,还有很多会发生panic的地方,交给你们自行学习吧~。
好啦,这篇文章就到这里啦,素质三连(分享、点赞、在看)都是笔者持续创作更多优质内容的动力!
Go interface 原理剖析--类型转换
大家好,我是 haohongfan,本文将从内存分配和汇编角度深入解析 Go 语言中的类型转换,特别是关于interface的原理。
尽管有许多关于interface转换的文章,但随着Go版本升级,汇编分析变得复杂。本文将不涉及动态转发和反射,主要探讨类型转换。常见的代码片段展示了interface转换的过程,但直接从汇编上看,interface转换为eface或iface的过程并不明显,需要借助调试工具gdb来观察。
通过内存分析,我们可以观察到eface的内存布局和类型转换结果。当我们分析 iface 的汇编时,虽然能见到它tab的存在,但是否真正转换成 iface,汇编层面的反映并不明确。通过gdb,可以验证Person接口确实被转换为了iface。
对于eface和iface的内存布局,可以使用unsafe函数查看内存位置的值。接下来,我们关注类型断言部分,汇编代码揭示了如何通过比较itab和接口实际类型信息来判断。
interface的一个常见陷阱是判断interface是否为nil。只有eface的type和data都为nil时,才会成立。复制b到interface时,即使data为nil,由于其他原因,可能不满足interface == nil的条件。
最后,对于阅读interface源码的建议,建议选择go1..x版本的Go,因为其汇编变化相对较小,能更好地观察interface转换和调用的细节。但如果版本过高,可能会影响汇编的可读性。