编程常见报错和解决方法
写代码像开车,起步的时候总觉得方向盘在自己手里,结果一上路,才发现仪表盘上红灯闪个不停。报错不是坏事,它是系统在用最直白的方式提醒你:这条路走不通。我刚开始学编程那会儿,最怕看到红色字符满屏飞,脑子里只剩一个念头:“完了,我又搞砸了。”后来才慢慢明白,报错其实是程序在跟你对话,哪怕它语气冲了点。
第一次被报错“教育”,是一个再普通不过的下午。那会儿我正照着教程敲一个登录页面,信心满满地按运行,浏览器却白屏,控制台里冒出来一行:Cannot read property 'value' of null。我当时愣了三秒,盯着那行字反复念,像在念咒语。后来才发现,HTML里把id="username"写成了id="usernmae",少了一个字母。整个页面找不到这个元素,代码却还在执着地要拿它的值,结果只能“空手而归”。那次之后我学乖了:只要看到“null”“undefined”之类的词,第一反应不是慌,而是去确认名字对不对、东西在不在。名字写错,是编程世界里最常见也最容易被原谅的错。

很多人觉得报错等于能力差,其实不然。我见过工作多年的开发,也会因为少写一个分号或者拼错变量名卡半天。有一回同事做数据统计,页面死活不刷新,日志里全是TypeError: xxx is not a function。大家围过去像会诊,最后发现他把一个普通对象当成函数去调用了。原因更简单:引入模块的时候,写了import { getData } from './data',可文件里导出的是export default。import和export没对上,函数自然“不存在”。这种错不丢人,它只是提醒你:模块之间的约定,得一条一条守。
还有一类报错,像个慢性子,平时不吭声,一到关键时刻发作。比如做条件判断时,不小心把==写成=,程序不报错,但逻辑全变了。用户明明没登录,却被告知“欢迎回来”,优惠券发了一堆却没扣库存。这种错最磨人,因为它不喊疼,只会在上线后悄悄制造事故。我也栽过跟头:一次循环里把i < 10写成i <= 10,多跑一轮,把不该清空的数据清掉了。测试阶段没发现,上线后半夜被消息炸醒。后来我在写判断和赋值时,强迫自己停一秒,像过马路前左右看一眼,错误率果然掉了一大截。
环境问题也是报错的重灾区。“在我电脑上跑得好好的,怎么一上线就崩?”这句话几乎成了程序员的接头暗号。有一回我写一个脚本,本地跑得很顺,部署到服务器却报错Module not found。折腾半天才发现,本地装了全局依赖,服务器是干净环境,版本还对不上。还有一次,时间戳在本地和线上差了八小时,排查半天,原来是时区没统一。环境就像路面,平整的时候不觉得,路坑一点,车就晃得厉害。后来我养成习惯:能写进配置文件的不靠记忆,能统一版本的不靠“差不多”。
数据库相关的报错,常常带着一种“郑重其事”的严肃感。duplicate entry、foreign key constraint、connection timeout,每个词都像在提醒你:数据的世界有规则,犯规就要付出代价。有一回我批量导入用户信息,报错说手机号重复。我第一反应是数据出错了,后来才发现,是脚本里没做去重,同一批数据被插了两遍。数据库不跟你讲情面,你不给主键、不建索引、不加事务,它就冷眼旁观,等你真的需要它的时候,再甩给你一串错误码。对付这类报错,我的经验是:先看日志,再看结构,最后再看代码。顺序不能乱,心不能急。
前端同学可能更熟悉网络请求的报错。404像是迷路,500像是服务器发脾气,CORS则像门口的保安不让进。有一回做跨域调用,浏览器控制台里全是红字,后端却说“我这接口正常”。来回拉扯两小时,最后发现是请求头里多写了一个字段,触发了预检请求,直接被拦下。网络请求的报错,很多时候不是谁对谁错,而是两边没对齐。参数、类型、头信息,哪怕差一个空格,都可能让请求“被消失”。后来我学会了用工具把请求抓下来,一条一条比对,像侦探找线索,反而比盲目改代码更快。
还有一些报错,像是系统故意留下的谜题。比如内存突然暴涨,页面卡成幻灯片,却看不到明显的错误行;或者定时任务跑着跑着就停了,日志干干净净。这时候靠肉眼已经不够,得靠工具。性能分析、堆栈跟踪、日志分级,这些一开始觉得麻烦的东西,关键时刻能救命。我记得有次排查一个偶发的崩溃,靠打印日志没用,最后打开性能面板,发现一个定时器没清理,一直在堆积闭包。关掉它的那一刻,页面像被松开了脖子,重新呼吸起来。工具不是魔法,但能让你少走弯路。
改报错最忌讳的,是“蒙”。看到红字就复制到搜索框,点开第一个答案就粘贴代码,以为这样就能过关。短期看是快,长期看是债。我见过有人把catch里写console.log改成// ignore,结果错误被吞掉,三个月后数据丢了才被发现。报错是信号,不能把它关掉,而要顺着它找到根。改完一次,最好多问一句:为什么会发生?下次怎么避免?这样改一次,水平就长一寸。
除了技术层面,心态也决定了你跟报错的相处方式。刚入门时,我把报错当成失败;后来把它当成路标;再后来,甚至有点喜欢它——它至少告诉我,程序在运行、在反馈、在等我解决问题。没人能一次写对,区别只在于,有人愿意停下来看懂它,有人急着绕开它。绕开的错,会在后面排队等你。
写到最后,我想把改报错的过程总结成几条不成文的小经验:先复现,再定位;先看日志,再看代码;先怀疑输入,再怀疑逻辑;先本地,再环境;先单步,再批量。每一步都不复杂,但坚持下来,效率会明显不同。工具要趁手,注释要诚实,版本要清晰,这些小事比“写出神级代码”更能让你睡得安稳。
编程这条路,不怕报错,怕的是对报错麻木。当你不再害怕满屏的红字,而是习惯性地皱起眉头、深吸一口气、然后开始一行一行排查时,你已经在成为更稳的开发者。报错不是终点,它只是程序在说:再试一次,换个方式,把问题解决掉。然后你会发现,页面亮了,数据对了,用户满意了,而你自己,也比上一次更懂这行代码的意义。