语言对比
已收录:本页沉淀 JavaScript / TypeScript / Python / Go / Rust 五门语言的对比笔记,覆盖「相同问题的不同解法」与「选型考量」。各语言的示例与踩坑细节请进入对应语言页:JavaScript、TypeScript、Python、Go、Rust。
五句话定位
| 语言 | 定位 | 一句话印象 |
|---|---|---|
| JavaScript | Web 全栈事实语言 | 单线程事件循环 + 动态类型,浏览器里唯一的选择 |
| TypeScript | JS 的超集(静态类型层) | 把 JS 的「自由」框进类型系统,大型前端标配 |
| Python | 胶水语言与数据科学 | 语法最易读、生态最广,性能靠 C 扩展兜底 |
| Go | 云原生后端与 CLI | 极简 + goroutine,把「并发」写成寻常语法 |
| Rust | 系统级性能与安全 | 零成本抽象 + 编译期内存安全,代价是陡峭学习曲线 |
总览对照表
| 维度 | JavaScript | TypeScript | Python | Go | Rust |
|---|---|---|---|---|---|
| 类型 | 动态 | 静态(结构化/可推断) | 动态(渐进注解) | 静态(简单强) | 静态(强 + trait) |
| 内存管理 | GC(V8) | 同 JS | 引用计数 + GC | GC(并发标记) | 所有权 + 编译期析构 |
| 运行模型 | 解释/JIT | 编译为 JS | 解释(CPython) | 编译为原生 | 编译为原生 |
| 并发原语 | 单线程 + 事件循环 + Worker | 同 JS | 线程 + GIL / asyncio | goroutine + channel | 线程 / async,编译期检查 |
| 空值表示 | undefined / null | 联合类型收窄 | None | 零值 + error | Option<T> |
| 错误处理 | 异常 throw | 同 JS | 异常 raise | 多返回值 + error | Result<T, E> |
| 多态 | 鸭子类型 | 结构化类型 | 鸭子 + ABC | 隐式接口 | trait 显式实现 |
| 包管理 | npm / pnpm | 同 JS | pip / uv | go mod | cargo |
| 构建/检查 | 无编译(bundler) | tsc | 无编译 | go build | cargo build |
| 测试 | 框架生态(Jest/Vitest) | 同 JS | pytest(stdlib unittest) | 内建 go test | 内建 cargo test |
| 进入成本 | 低 | 中 | 最低 | 中 | 高 |
| 适用主力场景 | 前端、Node 服务 | 前端工程、Node 服务 | 脚本、数据、AI | 后端 API、中间件、CLI | 性能关键、系统、基础设施 |
同题异解:相同问题,不同解法
① 集合变换:1..10 中偶数求和
js
// JavaScript
[...Array(10)].map((_, i) => i + 1).filter(x => x % 2 === 0).reduce((a, b) => a + b, 0)
// 30ts
// TypeScript(与 JS 运行时等价,编译期只剥类型)
const sum: number = Array.from({ length: 10 }, (_, i) => i + 1)
.filter(x => x % 2 === 0)
.reduce((a, b) => a + b, 0)py
# Python:生成器表达式最直观
sum(x for x in range(1, 11) if x % 2 == 0) # 30go
// Go:无流式 API,手写循环是惯例
sum := 0
for i := 1; i <= 10; i++ {
if i%2 == 0 {
sum += i
}
}rust
// Rust:迭代器链(惰性,零分配)
(1..=10).filter(|x| x % 2 == 0).sum::<i32>() // 30差异本质:JS/TS/Python/Rust 倾向「描述要什么」的声明式链式;Go 倾向「描述怎么做」的命令式(标准库刻意少魔法、类型简单)。Rust 的链在编译期内联、无中间分配,与 Go 手写循环性能相当。
② 可选值 / 空值(null safety 光谱)
js
// JavaScript:任何位置都可能 undefined,靠 ?. 与 ?? 兜底
const u = maybeUser(0)
const name = u?.name ?? '匿名' // 匿名py
# Python:None 可出现在任何值上,靠 if 判断
u = maybe_user(0)
name = u["name"] if u else "匿名"go
// Go:返回 (值, ok) 二元组,零值(nil map)不可直接读
func findUser(id int) (map[string]int, error) {
if id <= 0 { return nil, errors.New("无效 id") }
return map[string]int{"id": id}, nil
}
u, err := findUser(0)rust
// Rust:Option<T> 是普通类型,match/?/map 强制处理
fn find_user(id: i32) -> Option<User> {
(id > 0).then(|| User { id }) // 编译器不允许忽略 None 分支
}| 语言 | 空值语义 | 忘记处理的后果 | 兜底写法 |
|---|---|---|---|
| JS/TS | undefined/null 双空值 | 运行期 undefined is not a function | ?.、?? |
| TS(strict) | 类型系统可排除 | 编译期报错 | 收窄 if (u) {} |
| Python | None | 运行期 AttributeError | if x、or 默认 |
| Go | 零值 + 显式 error | 运行期 panic(nil 解引用) | comma-ok、err != nil |
| Rust | 编译期类型 | 编译期报错(穷尽匹配) | Option/Result 组合子 |
光谱从「运行期才能发现」(JS/Python) 到「编译期强制」(Rust/TS-strict)。Go 介于其间:nil 能编译但运行期炸,靠纪律约定。
③ 错误处理哲学
| 语言 | 机制 | 优点 | 代价/坑 |
|---|---|---|---|
| JS/TS | 异常 throw/catch | 栈自动带上下文 | 忘记 catch 程序崩溃;类型不标注错误种类 |
| Python | 异常 | 内置丰富(ValueError…) | 异常即控制流易滥用;性能开销 |
| Go | error 值 + 显式 if | 错误是普通值,流清晰 | 样板多(if err != nil 满天飞) |
| Rust | Result + ? | 类型化错误,? 自动 From 转换 | 自定义错误枚举需要样板(thiserror 缓解) |
go
// Go:处理每个错误是默认姿态
f, err := os.Open(path)
if err != nil { return err }rust
// Rust:? 把「成功继续 / 失败上抛」压成一行
let f = File::open(path)?; // io::Error → 自动转成函数返回的错误类型Rust 的
?本质是「Go 的 if err 的语法糖 + 自动类型转换」;Go 坚持显式换来简单一致,Rust 坚持类型化换来可组合。
④ 多态与接口
ts
// TS:结构化类型(鸭子类型 + 静态检查)
interface Speaker { speak(): string }
function greet(s: Speaker) { console.log(s.speak()) }py
# Python:鸭子类型(运行期),ABC 提供约束
def greet(s):
print(s.speak()) # 只要会 speak() 就行go
// Go:隐式接口——类型实现方法即自动满足,无需声明
type Speaker interface{ Speak() string }
func greet(s Speaker) { fmt.Println(s.Speak()) }rust
// Rust:显式 trait——必须写出 impl,编译期约束最严
trait Speaker { fn speak(&self) -> String; }
fn greet(s: &dyn Speaker) { println!("{}", s.speak()); }| 语言 | 实现关系 | 声明 | 检查时机 |
|---|---|---|---|
| JS | 结构匹配 | 无需 | 运行期(鸭子) |
| TS | 结构匹配 | 无需(implements 可选) | 编译期 |
| Python | 结构匹配 / ABC 注册 | 可选(ABC) | 运行期 |
| Go | 结构匹配(方法集) | 无需声明 | 编译期 |
| Rust | 名义 + 结构(trait 实现处声明) | 必须 impl | 编译期 |
同一条光谱:JS → Python → TS → Go 靠「形状一致」,Rust 最明确(写
impl Speaker for Dog),代价是代码多、换来方法集与 trait bound 的精确性(孤儿规则、对象安全等编译器保障)。
⑤ 并发:两个任务并行 + 等结果
js
// JavaScript:单线程事件循环,Promise.all 并发 IO
const [a, b] = await Promise.all([fetch(1), fetch(2)])py
# Python:asyncio 单线程事件循环(与 JS 同构)
a, b = await asyncio.gather(fetch(1), fetch(2))go
// Go:goroutine + channel,阻塞式同步写法,天然并行
ch := make(chan int, 2)
go fetch(1, ch); go fetch(2, ch)
a, b := <-ch, <-chrust
// Rust:async 显式 + 运行时(tokio),join! 并行等待
let (a, b) = tokio::join!(fetch(1), fetch(2));| 语言 | 并发模型 | 线程→语言能力 | 并行(多核)前提 |
|---|---|---|---|
| JS | 事件循环(单线程) | 无共享内存 | Worker 线程(消息传递) |
| Python | 线程(GIL)+ asyncio | GIL 限制 CPU 并行 | multiprocessing/C 扩展释放 |
| Go | goroutine(M:N,CSP) | 语言一等公民 | 默认多核,GOMAXPROCS 自动 |
| Rust | 系统线程 + async 运行时 | Send/Sync 编译期检查 | 线程直接并行,无锁数据靠类型 |
关键差异:JS/Python 的 async 是协作式单线程(不能真并行 CPU 计算);Go 的 goroutine 是运行时调度的 M:N 并发,channel 同步风格;Rust 要求你显式选择「线程 or async」,并把数据竞态挡在编译期。选型时先问「我要的是并发 IO(JS/Go 都行)还是多核并行计算(Go/Rust/多进程)」。
选型考量
场景 → 推荐
| 场景 | 首选 | 理由 | 备选 |
|---|---|---|---|
| Web 前端 / 跨端 | TypeScript | 唯一全生态、类型安全 | — |
| Node 后端 API | TypeScript | 与前端同语言,生态成熟 | Go(性能更高) |
| 常规后端服务 / 微服务 | Go | goroutine 简单、部署单二进制、云原生生态(K8s 系) | Rust(更高性能要求) |
| 高吞吐基础设施 / 系统组件 | Rust | 性能与内存安全,无 GC 停顿 | Go(开发更快) |
| 数据处理 / AI / 脚本自动化 | Python | 生态统治(numpy/pandas/torch)、迭代最快 | — |
| CLI 工具 / 运维小工具 | Go 或 Rust | 单文件静态分发、启动快 | Python(要装解释器) |
| 嵌入式 / FFI / 追求极致性能 | Rust | 无运行时、可裸机 | C(遗留) |
| 快速原型验证 | Python / TS | 最少代码量最快改 | — |
决策清单(选型自问)
- 团队会什么——语言生态与招人成本往往 > 语言本身的优劣;
- 瓶颈在哪——IO 密集选 goroutine/async 就够;CPU 密集才需要 Rust/Go 级并行与低开销;
- 可靠性要求——错误路径多、崩溃代价高的系统值得用 Rust/TS strict 把问题前移到编译期;
- 部署形态——「一个二进制到处跑」选 Go/Rust;「随叫随到的脚本」选 Python;
- 共享代码——前后端一体用 TS 全栈;别为「酷」引入第二门语言,除非有清晰收益;
- 生态成熟度——先查目标领域库是否完善(数据科学=Python、云原生=Go、前端=TS、嵌入式= Rust/C)。
常见误区
- 「Rust 更快所以服务全用 Rust」——多数 Web 服务的瓶颈是 IO 与数据库,Go 的开发效率优势更值钱;
- 「Python 太慢不能做后端」——GIL 内做 IO 并发(asyncio/多线程)足够服务大量连接,瓶颈通常在 DB;
- 「JS 单线程做不了并行」——Worker/子进程可用,但「计算并行」不是 JS 主场,别硬掰;
- 「TS 只是加类型」——类型系统还能表达可选性、区分度(字面量/模板类型),设计好了防一半运行期 bug;
- 「Go 没有泛型/异常所以落后」——Go 1.18+ 有泛型;error 值哲学换来的是全代码库一致的错误流,是取舍不是缺陷;
- 「Rust 所有权只是借用检查器添乱」——它把内存管理变成类型问题:数据结构设计对了,
&/&mut/Owned自然顺畅。
状态与参考
- 状态:已收录(2026-09-02,继五门语言页之后完成跨语言对照)。
- 运行环境:JS 示例基于 Node v20(TS 与 JS 运行时等价);Python 示例 Python 3;Go 示例 Go 1.26;Rust 示例 rustc 1.98 —— 集合变换与可选值示例均经实跑验证,输出见各小节注释。
- 参考:本模块各语言页(JS / TS / Python / Go / Rust)。
下一步
- [ ] 补充「同题异解」更多问题:字符串处理、日期时间、配置读取、JSON 序列化的五语言对照
- [ ] 对照「编译原理入门」规划,沉淀静态类型系统(TS/Go/Rust)之间的类型检查差异笔记
- [ ] 沉淀「跨语言协作」约定:同一 codebase 多语言边界(前端 TS、后端 Go、脚本 Python)的接口契约
写作规范与页面规划请参阅领域概览。