Description
Rust 是什么?
Rust 语言由 Mozilla 开发,最早发布于 2014 年 9 月。一门通用系统级编程语言。特点是高性能(系统级底层),高可靠性(内存安全)
Rust 可用于开发
- 命令行程序
- web 应用
- 网络服务器
- 嵌入式设备
- 机器人,区块链
https://www.rust-lang.org/zh-CN/
2021 Rust 行业报告
https://mp.weixin.qq.com/s/9rjeVgVzmrC0wWhV4wA9FA
Why Rust
-
大型前端项目的编译和构建,用 js 写的工具链等基础设施不能满足要求。
swc(Rust)、esbuild(go)的出现,越来越多的框架倾向于选择非 JavaScript 的编译工具来实现提速,Babel 不再是此方向的唯一选择。未来前端相关的基础设施都可能被 Rust 重写。
https://github.com/evanw/esbuild -
WebAssembly
安装
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
安装 rustup 工具链
判断是否正确的安装:
rustc --version
Hello World
- 新建一个 hello.rs
- 输入以下:
fn main() {
println!("hello world!");
}
- rustc hello.rs
- 执行:./hello
使用 Cargo
Cargo 是 Rust 工具链中内置的构建系统和包管理工具
- cargo new hello2
- 进入目录,执行:cargo build(构建项目)
- cargo build
- 直接执行 debug 的二进制文件
cargo run(构建+运行)
常用命令
版本更新
rustup update
查看版本
cargo --version
构建项目
cargo build
运行项目
cargo run
测试项目
cargo test
为项目构建文档
cargo doc
将库发布到 crates.io
cargo publish
说明
- TOML 一种配置文件格式,类似 json,yaml https://github.com/toml-lang/toml
- dependencies 项目依赖
需要用的包去 https://crates.io/ 找。类似 https://www.npmjs.com/ 。可自己发包。
cargo new --lib
核心概念
所有权系统
内存
管理内存
C/C++:这样的语言主要通过手动方式管理内存,开发者需要手动的申请和释放内存资源。如果没有正确的释放内存,容易产生 bug。(malloc申请内存)
Java:JVM 具备自动回收内存资源的功能。但这种方式常常会降低运行时效率,所以 JVM 会尽可能少的回收资源,这样也会使程序占用较大的内存资源。(通过垃圾回收完成内存的自动管理)
使用了包含特定规则的所有权系统来管理内存,这套规则允许编译器在编译过程中执行检查工作,来识别内存安全的问题。
设计了一套语法机制,使用这种语法在编译阶段就能更有效地分析内存资源的有用性以实现内存管理
编程语言的世界观
一门编程语言的诞生,一定有它想解决的问题。而围绕着这个问题。
所有权规则
- Rust 中的每个值都有一个变量,作为它的所有者。
- 同一时间内,值有且仅有一个所有者
- 当所有者离开自己的作用域时,它持有的值就会被释放掉
例子:
{ // 由于变量 s 还未被声明,所以它在这里是不可用的(如果访问,编译的时候就报错)
let s = "hello"; // 从这里开始变量 s 变得可用
// 执行与 s 相关的操作
} // 作用域到这里结束,变量 s 再次不可用(如果访问,编译的时候就报错)
- s 从进入作用域变得有效,
- 它会保持自己的有效性直到自己离开作用域为止
变量与数据交互的方式(数据传递)
js中值传递(基本数据类型)和引用传递(对象)
- 克隆(值传递)
- 移动
发生克隆的情况
- 栈上的数据
- 实现了 copy 的这种 trait 的数据类型(系统默认,u32,bool,char等类型实现了copy 的 trait)
trait 可以理解为接口。java 中的 interface。
发生移动的情况
- 堆上的数据
let x = 5;
let y = x;
println!("x = {}, y = {}",x, y); // 有效的
let x = String::from("hello");
let y = x
println!("x = {}", x); // 无效的
println!("y = {}", y); // 有效的
所有权与函数
fn main() {
let s = String::from("hello");
// s 被声明有效
takes_ownership(s);
// s 的值被当作参数传入函数
// 所以可以当作 s 已经被移动,从这里开始已经无效(和js表现不一样)
let x = 5;
// x 被声明有效
makes_copy(x);
// x 的值被当作参数传入函数
// 但 x 是基本类型,依然有效
// 在这里依然可以使用 x 却不能使用 s
} // 函数结束, x 无效, 然后是 s. 但 s 已被移动, 所以不用被释放
fn takes_ownership(some_string: String) {
// 一个 String 参数 some_string 传入,有效
println!("{}", some_string);
} // 函数结束, 参数 some_string 在这里释放
fn makes_copy(some_integer: i32) {
// 一个 i32 参数 some_integer 传入,有效
println!("{}", some_integer);
} // 函数结束, 参数 some_integer 是基本类型, 无需释放
有返回值的情况
fn main() {
let s1 = gives_ownership();
// gives_ownership 移动它的返回值到 s1
let s2 = String::from("hello");
// s2 被声明有效
let s3 = takes_and_gives_back(s2);
// s2 被当作参数移动, s3 获得返回值所有权
} // s3 无效被释放, s2 被移动, s1 无效被释放.
fn gives_ownership() -> String {
let some_string = String::from("hello");
// some_string 被声明有效
return some_string;
// some_string 被当作返回值移动出函数
}
fn takes_and_gives_back(a_string: String) -> String {
// a_string 被声明有效
a_string // a_string 被当作返回值移出函数
}
有返回值的函数,会将返回值的所有权移动到调用函数的地方。(s3获得所有权)
引用与借用
如果想调用一个函数,还能继续使用 String 呢?
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("The length of '{}' is {}.", s1, len); // 此时 s1 是有效的。如果上面一行不加「引用符号」&。那么 s1 就是无效的
}
fn calculate_length(s: &String) -> usize {
s.len()
}
「引用符号 &」
通过引用传递参数给函数的方法也被称为借用
默认是不可变引用。比如想要在 calculate_length 改变字符串的内容,是不会被允许的。需要
fn main() {
let mut s = String::from("hello");
// s 是可变的
change(&mut s);
}
fn change(some_string: &mut String) {
some_string.push_str("world");
}
引用规则:
- 在任何一段给定时间内,要么只能拥有一个可变引用,要么拥有任意数量的不可变引用。(原因:两个指针同时向同一空间写入数据会发生数据竞争,导致出错)
- 引用总是有效的
软件中缺陷
不同阶段和解决时间
- 不引入任何缺陷(理想情况) -- 无需解决时间
- 当敲下代码的那一刻,有缺陷的地方就能够被捕获到(language server,eslint,pritter) -- 秒级
- 编译期 or UT (Unit testing) 单元测试 -- 秒级到分钟级
- CI or code review 期间 -- 分钟 or 小时 or 天级(根据复杂度不同)
- 部署后研发或用户发现。 -- 天 or 月
早发现,早隔离,早诊断,早治疗
WebAssembly
概念
WebAssembly是一种新的编码方式,可以在现代的网络浏览器中运行 - 它是一种低级的类汇编语言,具有紧凑的二进制格式,可以接近原生的性能运行,并为诸如C / C ++等语言提供一个编译目标,以便它们可以在Web上运行。它也被设计为可以与JavaScript共存,允许两者一起工作。
诞生
C++ 经过 Emscripten 编译成字节码,字节码编译成 js
游戏改成 js 性能低,有了 asm.js
浏览器原生支持 WebAssembly
http://webassembly.org.cn/
https://developer.mozilla.org/zh-CN/docs/WebAssembly
现状
https://blog.scottlogic.com/2021/06/21/state-of-wasm.html
Rust 和 WebAssembly
有两大主要使用场景
https://developer.mozilla.org/zh-CN/docs/WebAssembly/Rust_to_wasm
- 构建完整应用 —— 整个 Web 应用都基于 Rust 开发!(例子 https://github.com/sheshbabu/rustmart-yew-example)
- 构建应用的组成部分 —— 在现存的 JavaScript 前端中使用 Rust
更好用的脚手架
https://github.com/lencx/vite-plugin-rsw
参考:
https://software-lab.org/publications/www2021.pdf
透过 Rust 探索系统的本原:编程语言
https://mp.weixin.qq.com/s?__biz=MzA3NDM0ODQwMw==&mid=2649828932&idx=1&sn=4a580c729ec39823d9d53ec65734ed3d
透过 Rust 探索系统的本原:内存管理
https://mp.weixin.qq.com/s/1juaadR3AqHa8H19sHWHmQ
十年磨一剑,WebAssembly 是如何诞生的?
https://mp.weixin.qq.com/s/rmvdVLeV049zcZs9dpTQ_A