我在 JavaScript 里用双等号判断相等,结果空字符串等于 0、字符串 0 等于数字 0,各种本不该相等的东西判出来都相等,我排查了大半天的复盘

我表单校验顺手用 == 判断,比如 if (value == 0)。结果用户没填(空字符串)时 "" == 0 返回 true、把空误判成 0,填字符串 "0" 也被当成 0,甚至

我在 JavaScript 里用双等号判断相等,结果空字符串等于 0、字符串 0 等于数字 0,各种本不该相等的东西判出来都相等,我排查了大半天的复盘

这是一个让我对 JavaScript 的 == 彻底死心、从此只用 === 的故事。我有段表单校验逻辑,要判断用户输入的值。我顺手用了 ==:比如 if (value == 0) 来判断"是不是 0"。测试时似乎没问题。可上线后,诡异的事接连发生:用户什么都没填(空字符串 ""),我的 value == 0 居然返回 true,把""误判成了"0";用户填了字符串 "0","0" == 0 也是 true;甚至我用 == 比较一些对象和值时,出现了 [] == 0true[] == ![] 也是 true 这种匪夷所思的结果。各种本不该相等的东西,判出来都"相等",我的逻辑被搅得一塌糊涂

我顺着这些反直觉的结果深挖,才终于揭开真相,补上了我对 JavaScript 一个最经典、也最容易被坑的认知漏洞:问题的核心,是 ==(抽象相等 / 宽松相等)的"隐式类型转换"。我一直想当然地以为,"== 就是判断两个东西相不相等";可真相是:== 两边的类型不同时,JavaScript 不会直接判定它们"不相等",而是会按一套极其复杂、且充满"陷阱"的规则,先把它们强制转换成相同的类型,再来比较。正是这个"先转换、再比较"的过程,制造了所有的诡异:比如 "" == 0——JS 会把空字符串 "" 转换成数字 0,于是 0 == 0 就成了 true;"0" == 0——把字符串 "0" 转成数字 0,也 true;而 [] == 0 更绕——空数组 [] 先转成空字符串 ""、再转成数字 0,于是 true;至于臭名昭著的 [] == ![]:![] 先算出 false,然后 [] == false,两边都往数字转,[]→0false→0,0 == 0true——一个"数组等于它自己的取反"的荒谬结论,就这么"合乎规则"地诞生了。我这才痛彻地明白:== 的隐式类型转换规则,极其复杂、反直觉、且几乎没人能完整记住;用它来做相等判断,就等于把代码的正确性,押注在一套连你自己都搞不清的转换规则上,各种"本不该相等却判成相等"的 bug,会防不胜防。而解药,简单得令人发指:永远用 ===(严格相等)——它不做任何类型转换:类型不同,直接判定不相等;只有类型相同、值也相同,才返回 true;它的行为简单、可预测、符合直觉,从根上杜绝了所有隐式转换的妖魔鬼怪

故障现场:== 的隐式类型转换,判出一堆诡异的相等

我把这些"诡异的相等"现场,摊开给你看:

// ✗ 灾难: 用 == 比较, 隐式类型转换制造一堆反直觉的"相等"
console.log("" == 0);       // ✗ true!  空字符串转成数字 0, 0 == 0
console.log("0" == 0);      // ✗ true!  字符串"0"转成数字 0
console.log(" " == 0);      // ✗ true!  空白字符串转成数字 0
console.log(false == 0);    // ✗ true!  false 转成数字 0
console.log(false == "");   // ✗ true!  两边都转成 0
console.log(null == undefined); // true (这个 == 的特例, 反而常用)
console.log([] == 0);       // ✗ true!  [] → "" → 0
console.log([] == "");      // ✗ true!  [] → ""
console.log([] == ![]);     // ✗ true!  ![]=false, []→0, false→0, 0==0
console.log([0] == false);  // ✗ true!  [0]→"0"→0, false→0

// 真实翻车场景: 表单校验
function check(value) {
    if (value == 0) {        // ✗ 想判断"是不是数字0"
        return "不能为0";
    }
}
check("");      // ✗ 返回"不能为0"! 但用户其实是"没填"(空字符串)
check("0");     // ✗ 也被当成了 0
check([]);      // ✗ 空数组也被当成 0

// 为什么? == 是"抽象相等", 类型不同时先隐式转换再比较:
//   - 一边数字一边字符串 → 字符串转数字。
//   - 有 boolean → boolean 转数字(true→1, false→0)。
//   - 对象 vs 原始值 → 对象先转原始值(toString/valueOf)再比。
//   - 规则极其复杂, 充满特例, 几乎没人能完整记住。

// 唯一的"良性特例": null == undefined 为 true(常用来判"空")。

// 根因: == 做隐式类型转换, 把不同类型"硬凑"成相等; 规则复杂反直觉,
//   导致大量"本不该相等却判成相等"的 bug。

看着这一串"颠覆三观"的 true,我才算彻底想明白了根源。问题的核心,是 ==(抽象相等)的隐式类型转换:当两边类型不同时,JS 会先按复杂规则把它们强转成同类型,再比较所以才有这些诡异结果:"" == 0(空串转数字 0)、"0" == 0(字符串转数字)、false == 0(false 转 0)、[] == 0([]→""→0)、[] == ![](![]=false,两边都转成 0)——全是 true放到真实的表单校验里就翻车了:if (value == 0) 本想判"是不是数字 0",结果check("")(用户没填)、check("0")check([]) 全被误判成了 0转换规则极其复杂:一边数字一边字符串→字符串转数字;有 boolean→转数字(true→1、false→0);对象 vs 原始值→对象先转原始值再比;充满特例,几乎没人能完整记住(唯一的"良性特例"是 null == undefined 为 true,常用来判空。)归根结底:== 做隐式类型转换、把不同类型"硬凑"成相等;规则复杂反直觉,导致大量"本不该相等却判成相等"的 bug——这,就是根源。

第一件事:搞懂 == 与 === 的区别

定位到根源,我必须把 ===== 的区别从根上彻底搞清楚:

== 抽象相等(转类型再比), === 严格相等(类型不同直接不等)

# === 严格相等(strict equality):
#   - 先看类型: 类型不同 → 直接 false(不做任何转换!)。
#   - 类型相同 → 再比值。
#   - 行为简单、可预测、符合直觉。
#   例: "" === 0     → false(类型不同)
#       0 === 0      → true
#       "0" === 0    → false

# == 抽象相等(loose equality):
#   - 类型相同 → 同 ===。
#   - 类型不同 → 按复杂规则隐式转换后再比(坑就在这)。
#     * 数字 vs 字符串 → 字符串转数字。
#     * boolean 参与 → boolean 转数字。
#     * 对象 vs 原始值 → 对象转原始值(ToPrimitive)。
#     * null == undefined → true(特例); 但 null/undefined 不等于其他任何值。
#     * NaN == 任何 → false(包括 NaN == NaN 也是 false!)

# 那一堆诡异结果的推导(都是"先转换"惹的祸):
#   "" == 0      : "" 转数字 → 0, 0==0 → true
#   [] == 0      : [] 转原始值 → "", "" 转数字 → 0, → true
#   [] == ![]    : ![]=false; []→0, false→0; 0==0 → true

# 结论: 几乎没有理由用 ==(除了 x == null 判空这一个惯用法)。
#   - == 的转换规则太复杂, 记不全, 也没必要记。
#   - 一律 ===, 让"类型不同就不相等", 简单又安全。

# 顺带: NaN 的坑(唯一 === 也搞不定的)
#   NaN === NaN → false! 判断 NaN 要用 Number.isNaN(x) 或 Object.is(x, NaN)。

# 关键认知: 默认全用 ===; == 只在"x == null 同时判 null 和 undefined"时才用。

# 核心: == 会隐式转类型再比(规则复杂反直觉), === 类型不同直接 false(简单可预测);
#   一律用 ===, 仅 x == null 判空是良性特例; NaN 判断用 Number.isNaN。

原理终于清晰了。=== 严格相等:先看类型,类型不同直接 false(不做任何转换!),类型相同再比值——行为简单、可预测、符合直觉("" === 0 是 false、"0" === 0 是 false)。== 抽象相等:类型相同时同 ===;类型不同时,按复杂规则隐式转换后再比——数字 vs 字符串转数字、boolean 转数字、对象转原始值、null == undefined 为 true(特例)、NaN == 任何 都 false(坑就在这堆规则里)。那串诡异结果,全是"先转换"惹的祸:"" == 0(""→0)、[] == 0([]→""→0)、[] == ![](![]=false,两边转 0)。结论很干脆:几乎没有理由用 ==(除了 x == null 判空这一个惯用法)——转换规则太复杂、记不全、也没必要记;一律 ===,让"类型不同就不相等",简单又安全顺带还有个 NaN 的坑:NaN === NaN 也是 false!判断 NaN 要用 Number.isNaN(x)Object.is(x, NaN)由此,我刻下一个关键认知:默认全用 ===;== 只在"x == null 同时判 null 和 undefined"时才用。归根结底:== 会隐式转类型再比(规则复杂反直觉),=== 类型不同直接 false(简单可预测);一律用 ===,仅 x == null 判空是良性特例;NaN 判断用 Number.isNaN

第二件事:正解——一律用 ===,判空用 == null

搞懂了原理,正解极其简单:所有相等判断,一律用 ===;唯一保留 == 的地方,是 x == null 这个判空惯用法

// ✓ 正解一: 所有相等判断, 一律用 ===
if (value === 0) { ... }     // ✓ 只有真的是数字 0 才进, "" / "0" / [] 都不会
"" === 0;     // ✓ false(类型不同)
"0" === 0;    // ✓ false
[] === 0;     // ✓ false
0 === 0;      // ✓ true(类型值都同)

// ✓ 正解二: 表单校验, 用 === 精确判断
function check(value) {
    if (value === "") return "不能为空";       // ✓ 精确判空字符串
    if (value === 0) return "不能为数字0";      // ✓ 精确判数字0
    if (Number(value) === 0) return "值为0";   // ✓ 想把"0"也算0? 显式转换, 意图清晰
}

// ✓ 正解三: 唯一保留的 == —— 同时判 null 和 undefined
if (x == null) { ... }       // ✓ 等价于 x === null || x === undefined(简洁惯用法)
// 等价但啰嗦: if (x === null || x === undefined)

// ✓ 正解四: 判 NaN 用 Number.isNaN(=== 也搞不定 NaN)
if (Number.isNaN(x)) { ... } // ✓ 别用 x === NaN(永远 false)

// ✓ 正解五: 想做类型转换? 显式转, 别靠 == 隐式转
if (Number(input) === 100) { ... }   // ✓ 意图明确: 我就是要把它当数字比
// ✗ 别写 if (input == 100) 靠 == 偷偷转 —— 意图不清, 还可能出意外

// 用 ESLint 强制约束:
//   "eqeqeq": ["error", "always", { "null": "ignore" }]
//   → 禁止 ==/!=(强制 ===/!==), 但允许 == null 判空。

// 核心: 一律用 ===(类型不同直接不等, 简单可预测); x == null 判空是唯一良性特例;
//   要转类型就显式 Number()/String(); 判 NaN 用 Number.isNaN; 用 ESLint eqeqeq 强制。

修复极其简单,却根除了一整类 bug。正解一,所有相等判断一律用 ===:value === 0 只有真的是数字 0 才成立,""/"0"/[] 都不会误中。正解二,表单校验用 === 精确判断:想判空字符串就 value === ""、想判数字 0 就 value === 0,各判各的、清清楚楚;如果你确实想把字符串 "0" 也当 0,就显式 Number(value) === 0,意图清晰正解三,唯一保留的 ==:x == null 同时判 nullundefined(等价于 x === null || x === undefined 但更简洁,是公认的良性惯用法)。正解四,判 NaN 用 Number.isNaN(x)(=== 也搞不定 NaN,别用 x === NaN)。正解五,想转类型就显式转(Number(input) === 100,意图明确),别靠 == 偷偷转。最后,用工具强制约束:ESLint 的 eqeqeq 规则(["error", "always", { "null": "ignore" }])——禁止 ==/!=、强制 ===/!==,但允许 == null 判空归根结底:一律用 ===(类型不同直接不等、简单可预测);x == null 判空是唯一良性特例;要转类型就显式 Number()/String();判 NaN 用 Number.isNaN;用 ESLint eqeqeq 强制。

第三件事:JS 类型转换的几个其他高频坑

这次 == 的坑,根子是 JS 的隐式类型转换。我顺势把 JS 里其他几个由"隐式转换"引发的高频坑,也一并梳理清楚了:

// JS 隐式类型转换引发的其他高频坑:

// 坑1: + 运算符 —— 字符串拼接 vs 数字相加, 看类型
console.log(1 + "2");    // ✗ "12"(数字转字符串拼接!)
console.log(1 + 2 + "3"); // "33"(先算1+2=3, 再拼)
console.log("1" - 1);    // 0 (- 只能数字, 字符串转数字)
//   → + 有歧义, 想拼接用模板字符串 `${a}${b}`, 想相加先 Number()。

// 坑2: 真值/假值(falsy)判断
//   假值(falsy): false, 0, "", null, undefined, NaN, 0n
if (value) { ... }       // ✗ 0、""、NaN 都会进 else(可能非你所愿)
//   → 想精确判"有没有值", 用 value != null 或 value !== undefined。

// 坑3: 排序默认按字符串(见 sort 篇)
[1, 10, 2].sort();       // ✗ [1, 10, 2](按字符串"1","10","2")

// 坑4: 数组/对象转字符串的诡异
console.log([1,2] + [3,4]);   // ✗ "1,23,4"(都转字符串再拼)
console.log({} + []);          // 诡异, 看上下文

// 坑5: parseInt 的隐患
parseInt("08");          // 现代是 8, 老引擎可能当八进制
parseInt("12px");        // 12(它会"尽力解析"前面的数字)
Number("12px");          // NaN(更严格)
//   → 要严格转数字用 Number()/+, parseInt 用于"提取前缀数字"。

// 核心: JS 大量隐式类型转换坑(+歧义、falsy判断、转字符串诡异、parseInt宽松);
//   尽量显式转换(Number/String/模板串)、用 ===、判空用 != null, 别靠隐式转换。

原来 == 只是 JS 隐式转换坑的冰山一角坑一,+ 运算符的歧义:1 + "2""12"(数字转字符串拼接)、"1" - 10(- 把字符串转数字)——想拼接用模板字符串、想相加先 Number()坑二,真值/假值(falsy)判断:假值有 false/0/""/null/undefined/NaN,if (value)0/""/NaN 也会进 else(可能非你所愿,想精确判"有没有值"用 value != null)。坑三,排序默认按字符串([1,10,2].sort()[1,10,2]);坑四,数组/对象转字符串的诡异([1,2]+[3,4]"1,23,4");坑五,parseInt 的宽松(parseInt("12px")12、而 Number("12px")NaN)。它们的共同根源都是 JS 那套"无处不在的隐式类型转换"。归根结底:JS 有大量隐式类型转换的坑(+ 歧义、falsy 判断、转字符串诡异、parseInt 宽松);应对之道是——尽量显式转换(Number/String/模板串)、用 ===、判空用 != null,别靠隐式转换

下面这张图,是这次"== 诡异相等"的成因与解法:

第四件事:== 那些经典"反直觉相等"对照

这次踩坑后,我把 == 那些最经典、最坑的"反直觉相等",整理成一张表,看一遍就知道为什么该躲开它。

表达式 == 结果 === 结果 为什么 == 是这样
"" == 0 true ✗ false ✓ "" 转数字得 0
"0" == 0 true ✗ false ✓ "0" 转数字得 0
false == 0 true ✗ false ✓ false 转数字得 0
null == undefined true false == 的特例(常用于判空)
[] == 0 true ✗ false ✓ []→""→0
[] == ![] true ✗ false ✓ ![]=false, 两边转0
NaN == NaN false false NaN 不等于任何值(含自己)

这张表,把 == 的"魔幻"展示得淋漓尽致。== 那一列,全是反直觉的 true("" == 0"0" == 0[] == 0[] == ![]);再看 === 那一列,清一色规规矩矩的 false——因为它们类型不同,=== 直接判不相等,符合直觉这一列列的对比,胜过千言:== 用一套"没人记得住的转换规则",制造了一堆"本不该相等"的相等;而 ===,只是诚实地说"类型都不一样,当然不相等"(两个值得记的:null == undefined==良性特例,NaN 连自己都不等于、要用 Number.isNaN。)它给我的启发是:当一个特性的行为,复杂到需要一张表、甚至一篇文章才能勉强讲清,而它的替代品(===)却简单到一句话就说明白时,选择那个简单的,几乎总是对的== 那些"魔幻"的相等,从来不是什么"高级技巧",而是纯粹的、应该被坚决避开的复杂度陷阱

第五件事:为什么"显式优于隐式"是 JS 的护身符

== 的坑,本质是"隐式转换"的坑。这次让我深刻体会到,在 JS 里坚持"显式"有多重要。我把相关的"显式 vs 隐式"对照梳理了一遍。

意图 ✗ 隐式(易坑) ✓ 显式(清晰)
判断相等 a == b a === b
转成数字 "5" * 1 / +"5"(隐晦) Number("5") / parseInt
转成字符串 x + "" String(x) / `${x}`
转成布尔 !!x Boolean(x)(或明确条件)
判"有没有值" if (x)(0/""也算无) if (x != null)
数字拼接还是相加 a + b(看类型, 歧义) Number(a)+Number(b) / `{b}`

这张表,把"显式优于隐式"这条原则,落到了 JS 的具体写法上。左边那些"隐式"的写法(==x + ""!!xif (x)),都依赖 JS 那套"自动、隐藏"的类型转换——它们写起来短,却把"到底发生了什么转换"藏了起来,既容易出意外,也让读代码的人(包括未来的你)看不清意图。而右边那些"显式"的写法(===Number()String()Boolean()x != null),明确地写出了"我要做什么转换、做什么判断",行为可预测、意图一目了然它给我的最大启发是:在 JavaScript 这门"到处都是隐式转换"的语言里,"坚持显式"几乎是一条最重要的护身符;每一次,当你偷懒用了一个"隐式"的简写,你都是在把代码的行为,交给 JS 那套晦涩规则去裁决,也是在给未来的 bug,留下一个温床多打几个字、把意图明明白白地写出来——这点"啰嗦"换来的,是行为的确定和代码的可读,这笔买卖,永远划算

第六件事:写一个相等/类型判断时,我现在会怎么决策

现在,每当我在 JS 里写一个相等或类型判断,脑子里都会过一遍这张决策图——核心就一条:默认 ===,显式转换,别靠隐式。

这张图的灵魂,是一条近乎绝对的默认规则:判断相等,默认用 ===、绝不用 ==少数例外清清楚楚:判 null/undefinedx == null(或显式 === null)、判 NaNNumber.isNaN真值判断想精确就用 x != null 别只 if (x)(免得 0/"" 被当无值)。需要跨类型比较时:显式 Number() 转换后再 ===(意图清晰),别靠 == 偷偷转最后,把这条规则用工具固化下来:ESLint 的 eqeqeq,强制全队都用 ===这套判断,让我(和团队)从此告别 == 那些防不胜防的妖魔鬼怪——核心始终是:默认 ===,要转换就显式转,别把正确性交给隐式规则。

我立下的几条规矩

这场"== 诡异相等"的事故,换来了我写 JavaScript 时,刻进骨子里的几条铁律:

  1. 相等判断,默认用 ===,绝不用 ==。=== 类型不同直接 false、简单可预测;== 的隐式转换规则复杂反直觉,记不住也不该记。
  2. 唯一保留 == 的地方:x == null。同时判 null 和 undefined 的良性惯用法,其余一律 ===。
  3. 判 NaN 用 Number.isNaN。NaN 不等于任何值(连自己都不等),=== 也搞不定它。
  4. 要跨类型比较就显式转换。想把 "0" 当 0,就 Number(x) === 0,意图清晰;别靠 == 偷偷转。
  5. 真值判断要精确。想判"有没有值"用 x != null,别只 if (x)——0、""、NaN 都是假值会被误判。
  6. 显式优于隐式。转数字 Number()、转字符串 String()/模板串、转布尔 Boolean(),别用 +""、!!、隐式拼接。
  7. 用 ESLint eqeqeq 强制。把"只用 ==="变成团队的硬约束,而不是靠每个人的自觉。

附:几行代码亲眼看清 == 的隐式转换过程

口说无凭。下面这几段,把 == 的隐式转换过程"拆开"演示一遍,你会看到那些诡异结果是怎么"合乎规则"地推导出来的,跑一遍胜过千言:

// 实验1: "" == 0 的推导
console.log("" == 0);          // true
console.log(Number(""));        // 0  ← "" 转数字得 0
//   所以 "" == 0  等价于  Number("") == 0  →  0 == 0  →  true

// 实验2: [] == ![] 这个"名场面"的推导
console.log([] == ![]);        // true
console.log(![]);               // false        ← ① ![] 先算: [] 是真值, 取反得 false
console.log(Number(false));     // 0            ← ② false 转数字得 0
console.log(Number([]));        // 0            ← ③ [] → "" → 0
//   所以 [] == ![]  →  [] == false  →  0 == 0  →  true

// 实验3: [] == 0 的推导(对象转原始值)
console.log([] == 0);          // true
console.log([].toString());     // ""           ← [] 转原始值(toString)得 ""
console.log(Number(""));        // 0            ← "" 再转数字得 0
//   所以 [] == 0  →  "" == 0  →  0 == 0  →  true

// 实验4: 用 === 全部恢复正常
console.log("" === 0);         // false ✓
console.log([] === 0);         // false ✓
console.log([] === ![]);       // false ✓
console.log("0" === 0);        // false ✓
//   === 类型不同直接 false, 不做任何转换 —— 干净利落

// 实验5: NaN 的特殊
console.log(NaN == NaN);       // false (连自己都不等)
console.log(NaN === NaN);      // false
console.log(Number.isNaN(NaN)); // true ✓ 这才是判 NaN 的正道

// 核心: 把 == 的每一步隐式转换(Number()/toString()) 拆开打印, 诡异结果就"理所当然"了;
//   而 === 一律 false, 简单到无需推导。眼见为实。

这几段代码,把 == 的"魔法",拆解成了一步步可见的转换实验 1 拆开 "" == 0:Number("")0,于是 0 == 0 自然为 true。实验 2 拆开那个臭名昭著的 [] == ![]:![] 先算出 false(因为 [] 是真值)、② false 转数字得 0、③ []toString""、再转数字得 0,所以最终是 0 == 0 为 true——一个"数组等于自己取反"的荒谬结论,被一步步"合乎规则"地推了出来实验 3 拆开 [] == 0([]→""→0);而实验 4 一换成 ===,全部干净利落地回到 false——因为它类型不同就直接判不等、根本不做这些转换实验 5 则展示了 NaN 连自己都不等、要用 Number.isNaN这,正是我想用这几段代码,留给每一个写 JS 的人的最后一课:那些看起来"诡异、不可理喻"的结果,一旦你把它背后的转换步骤一步步拆开、亲手打印出来,就会发现它们"诡异得很有道理"——只是这套"道理"太复杂、太不该让人去记。而这恰恰反证了:与其去理解和记忆这套复杂的转换规则,不如直接用 === 绕开它看清一个坑的来龙去脉,是为了更坚定地避开它,而不是为了炫耀你能驾驭它

写在最后

回头看,这场由 == 引发的事故,真正教给我的,是一个比"用 ===" 本身更深的道理:语言为了"方便"而提供的某些"智能"特性(比如自动帮你做类型转换),常常是一把双刃剑;它看似"贴心地替你省事",实则把"到底发生了什么"藏进了一套你难以掌控的暗箱规则,从而用"表面的便利",换走了你"对代码行为的确定性把控"== 的"自动类型转换",当初设计的本意,或许是想让比较"更灵活、更宽容";可这份"过度的宽容",最终却变成了无数 bug 的温床——它太想"猜测我的意图",却猜得一塌糊涂,还把我蒙在鼓里。这让我深刻地领悟到:好的工具、好的代码,追求的不是"聪明地猜你想干什么",而是"诚实、可预测地、精确做你明确让它做的事";"明确(explicit)"和"可预测(predictable)",远比"智能(magic)"更有价值所以,无论是用语言特性,还是设计自己的 API,我都更倾向于选择和创造那些"行为明确、没有暗箱"的东西:宁可多写一个字、多一份"啰嗦"的显式,也不要那份"替我做了主、却又不告诉我"的"隐式聪明"在"魔法般的便利"和"诚实的可预测"之间,永远选后者——这,是我用一次"== 诡异相等"的事故,换来的、关于 JavaScript、也关于"如何选择和设计工具"的、最朴素也最深刻的领悟。如果这篇复盘,能让你从此== 换成 ===,并对一切"过度智能"的隐式行为多一分警惕,那我对着那些诡异的相等熬的这大半天,就值了。

—— 别看了 · 2026
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理 邮箱1846861578@qq.com。
技术教程

我在 Python 里用 is 判断两个数字相不相等,小数字时一直好好的,换成大数字后判断突然全错了,我对着这个时对时错的比较排查了大半天的复盘

2026-6-2 3:37:06

技术教程

我的 Go 服务在高并发下突然整个崩了、还打出 fatal error concurrent map read and map write,我对着这个连 recover 都拦不住的崩溃排查了大半天的复盘

2026-6-2 3:49:40

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索