Rust核心概念

这期我们来唠唠 Rust 的"核心五大护法",这几个概念是 Rust 世界的地基,理解它们之后,你再看 Rust 就像"武林秘籍看目录",豁然开朗。我会从"前端视角"来比喻,结合 JS/TS 帮你建立联系。


🥇 所有权(Ownership)------Rust 的"内存保安队长"

在 JS 里,你从来没管过内存,new 也好,数组也好,变量用完就等 GC 回收。但 Rust 没 GC,它靠所有权系统来"自动管理内存"。

通俗讲:

在 Rust 里,每块内存只会有一个"所有者变量"。当所有者变量离开作用域,这块内存就自动释放。

举个例子:

rust 复制代码
fn main() {
    let s1 = String::from("hello");
    let s2 = s1;  // s1 把所有权给了 s2,自己就不能用了
    println!("{}", s1); // ❌ 编译报错:s1 已被移动
}

就像 JS 里的变量 s1 = 'hello';你把它"转手给了 s2",但 Rust 会说:"那 s1 就不能用了哈,我要保证你不会用到无效数据"。

编译期强制你安全编程,这就是 Rust 的牛逼之处。


🥈 借用(Borrowing)------变量"出借",但不能"转让"

那你可能说:"我不想把变量完全交出去,只是借它用一下。"这时候就轮到 Rust 的"借用"机制了。

类比 JS:

js 复制代码
function double(arr) {
  return arr.map(x => x * 2);
}

你传的是个引用,对吧?Rust 里也能借用变量,不转移所有权:

rust 复制代码
fn double(arr: &Vec<i32>) {
    for x in arr {
        println!("{}", x * 2);
    }
}

fn main() {
    let v = vec![1, 2, 3];
    double(&v);  // 借用 v,不移动所有权
    println!("{:?}", v); // ✅ OK,v 还能用
}

Rust 区分:

  • &T:不可变借用,多个可以共存
  • &mut T:可变借用,只能有一个

核心思想:你要么多个读者,要么一个作者,不能又读又写,这样就不会数据冲突。


🥉 生命周期(Lifetimes)------借用的"生死时限"

这听起来吓人,其实是为了解决一个问题:你借的东西,不能比原来活得久。

想象下这个 JS 场景:

js 复制代码
let result;
{
  const temp = "hello";
  result = temp;  // temp 出作用域就挂了,但你还在用 result
}
console.log(result);  // ❌ 潜在问题

Rust 编译器会捕捉这种情况,它要你声明:这个借用能活多久

rust 复制代码
fn get_first<'a>(s: &'a str) -> &'a str {
    &s[0..1]
}

'a 就是生命周期标注,它告诉编译器:传进来的引用,返回值的生命周期不能超过它。

你平时用编译器推断就够了,出问题再显式标注。


🟦 匹配模式(match)------比 switch-case 高级一百倍

JS 有 switch-case,Rust 有 match,但它不仅能匹配值,还能解构、匹配类型、绑定变量,非常强。

rust 复制代码
fn main() {
    let x = Some(5);
    match x {
        Some(1) => println!("one"),
        Some(n) => println!("value is {}", n),
        None => println!("none"),
    }
}

像是类型 + 模式匹配的结合体,有点像 JS 里的:

js 复制代码
const x = { type: 'Some', value: 5 };
switch (x.type) {
  case 'Some': console.log(x.value); break;
  case 'None': console.log('none'); break;
}

但 Rust 写法更简洁,特别适合和枚举/错误处理配合使用


🟥 枚举 + 错误处理(Option / Result)------告别 null、try-catch 的新姿势

Rust 没有 nullundefined 这些让人崩溃的玩意儿。取而代之的是:

1. Option<T> 表示可能有值,也可能没值:

rust 复制代码
let name: Option<String> = Some("Tom".to_string());

match name {
    Some(n) => println!("Hello, {}", n),
    None => println!("No name"),
}

2. Result<T, E> 表示可能成功,也可能失败(比如文件读取、网络请求):

rust 复制代码
fn divide(a: i32, b: i32) -> Result<i32, String> {
    if b == 0 {
        Err("Cannot divide by zero".to_string())
    } else {
        Ok(a / b)
    }
}

fn main() {
    match divide(10, 2) {
        Ok(val) => println!("Result: {}", val),
        Err(e) => println!("Error: {}", e),
    }
}

这种做法好在哪?

  • 编译器强制你"必须处理错误"
  • 再也不会有"调用了 null 的 toString 报错"这种事

是不是很像 TS 的 EitherOption 泛型类型,但更原生、更好用?


总结:核心概念速查表

概念 通俗解释 JS 类比
所有权 谁负责释放内存 没有 GC,要自己守规则
借用 引用变量但不转让 像引用参数,JS 默认传引用
生命周期 借用变量活多久 闭包/作用域变量别用晚了
匹配模式 花式 switch-case 解构 + 类型判断的组合拳
Option / Result 安全处理空值和错误 告别 null、try-catch 的未来式

相关推荐
red润7 分钟前
JavaScript 二维数组初始化:为什么 fill([]) 是个大坑?
前端·javascript·代码规范
一生躺平的仔15 分钟前
Electron 应用时间校准深度探索:从客户端策略到主进程优化
前端
wordbaby15 分钟前
从前端开发者视角解析依赖注入:解耦与可维护性的核心范式
前端
玲小珑15 分钟前
Auto.js 入门指南(一)什么是 Auto.js
android·前端
满分观察网友z21 分钟前
揭秘 Intersection Observer:让你的网页“活”起来!
前端·javascript
小佐_小佑21 分钟前
如何用 pnpm patch 给 element-plus 打补丁修复线上 bug(以 2.4.4 修复 PR#15197 为例)
前端
nvvas27 分钟前
前端Nodejs报错:Browserslist: caniuse-lite is outdated. Please run: npx update...
前端
Data_Adventure1 小时前
Vite 项目中使用 vite-plugin-dts 插件的详细指南
前端·vue.js
八戒社1 小时前
如何使用插件和子主题添加WordPress自定义CSS(附:常见错误)
前端·css·tensorflow·wordpress
xzboss1 小时前
DOM转矢量PDF
前端·javascript