这是我参与更文挑战的第12天,活动详情查看:更文挑战
写在前面的话
在开发阶段,debug十分重要,合理使用断点能够帮助我们快速定位问题。但是很可惜几乎没有这类文章来总结,也许是太简单?所以当时我自学的时候十分不确定我debug的姿势是否正确。因此我来分享一下我是如何Debug的吧。(大神可直接跳过)
为了涵盖更广的范围,这里我们讲的是从页面请求,到后端整个过程的debug。
前提:使用Debug模式启动代码(一般来说,开发过程中run模式其实没什么用)
找到请求入口
首先要知道请求的url是什么,F12打开开发人员调试器。我们以zhuanlan.zhihu.com/p/272065407 这个网址为例子。我们只关注数据的请求,因此只需要选择XHR(XMLHttpRequest)选项。
对的,现在一般一个页面的查询,会有多个url请求组成,有的是获取正文内容,有的是获取照片,有的是获取评论。by the way 一般系统设计这些都会做成单独的微服务。
看url的名字,我们大概可以猜到www.zhihu.com/api/v4/arti… 这个请求是查询评论的。我们可以通过点击右下方的response,看看服务端返回的数据内容,就能确定具体是获取什么的请求。
当然你可以直接把这个url复制到浏览器地址栏中直接查询获取结果。
代理转发到本地
如果是前后端没有分离的项目,也就是一般前后端代码在一个代码工程中的,可以直接看下一面的步骤。
对于前后端完全分离的项目,我们后端人员一般是没有前端的代码的,因此不能本地启动前端代码,本地发送前端请求。这个时候一般有两种方式,一个是使用postman来发送请求到本地,但是往往要设置请求的一些cookies或者headers,稍微有点麻烦。另外一种方式就是开启代理。
先解释一下代理的字面意义,举个栗子,我们要买一个轿车,可以全靠自己来实现,自己找车源,自己办理过户手续,车间手续,但是也可以找个中介公司来帮我们处理,于是我们要做的事情请就是找一家中介公司,然后委托他们帮我们(代理)买辆车。
我们这里代理的作用就是,把页面的请求拦截住,然后根据事先设定好的规则,代理「转发」到本地启动的代码上。
例如charles软件,我们会在tools—> map remote中设置
from就是我们要拦截的http/https请求,to就是将要代理转发给本地的IP。下图大致就是把url为www.zhihu/api/v3/arti…
找到后端代码入口
有了请求url,我们要开始找后端入口。一般而言任何项目都会有地址转换映射,例如这个www.zhihu.com/creator/ana…
当你知道了前端url到后端的映射规则后,你就更加容易找到后端代码入口。假设www.zhihu.com/creator/ana…
对于项目结构组织好的,通过文件夹名,包名能够更快的确认。如果不确定,我们可以在这段代码的第一行就打上断点,页面发送请求,看看代码是否在断点位置中断了。
当然了,也有url不是映射的情况,可以直接全局搜索url关键字找到后端代码入口。大胆猜测上面的例子www.zhihu.com/api/v4/arti…
断点的几个按钮
这一部分是最基本的打断点说明。我用Goland做演示(其实和eclipse一样)。
- 执行下一个方法:可以认为是一行行的执行,例如上面的执行完func1(),就会在func2()哪一行停住。
- 进入方法:当我们在func1()点击进入方法的时候,就会在28行停住(和上图打了断点无关)。
- 退出方法:当进入了28行后,点击退出方法,就会回到8行。也就是退出该方法。
- 执行到下一个断点:如上图执行到第8行,点击了执行下一段断点,便会在28行停住。
- 屏蔽所有断点:断点无效,相当于以run模式执行。
观察变量值的变化
学会观察变量的值,获取蛛丝马迹信息。查看变量信息如下图,一般有两个地方可以看到(eclipse不支持在每一行代码处查看)。但是对于一些循环和条件判断比较多的代码,我们可以直接把变量打印出来查看,打印的信息在左下角的console中切换查看。
断点位置
尽量多的打断点,以此精确找出问题的代码位置。对于不熟悉的代码,不太可能一次就能够在错误代码处打上代码,往往会一次次的错过代码。一般要结合执行下一步+进入方法两个方式找到问题代码。
同时有时候,代码使用了装饰器模式,或者一个接口有多个实现办法,不熟悉代码,可能不知道具体会进哪个实现方法中,这时候就可以每个实现方法入口都打上断点。
还有一种情况,有些地方会经过多个业务校验规则,有时候会需要知道这些业务规则的执行顺序,就会需要每个业务规则代码都打上断点,来得到他们的执行顺序。
多线程Debug
多线程的Debug有时候需要手动切换线程,来观察具体线程的情况(为了和Java统一,下面Go语言的协程就统一说成线程了)。例如下图(理解go func这个就是多开了一个线程,相当于java的new Thread().run()),看箭头处,它目前处于main这一个线程。
而实际它背后还有一个线程在跑,我们点击箭头处可以进行切换Goroutine18,然后点击执行下一步,这个线程就会继续执行下去。
值得一提的是,在我们debug多线程程序的时候,有时候会发现预想的线程并没有执行,这是因为我们的主线程(一般就是main线程)已经执行完成了,所以直接退出了整个程序。这个时候我们应该在主线后添加一个休眠逻辑,或者循环逻辑来保证主线程不会马上退出。
最后
Debug的流程大致就是这样,总的来说就是,先找url,再找后端代码入口,多打断点,逐步锁定问题代码。