正式开始
安装
VS常用的Rust插件
- rust-analyzer:实时编译和分析 Rust 代码,提示代码中的错误,并对类型进行标注。
- rust syntax:为代码提供语法高亮。
- crates:分析当前项目的依赖是否是最新的版本。
- better toml:Rust 使用 toml 做项目的配置管理。better toml 可以语法高亮,并展示 toml 文件中的错误。
- rust test lens:快速运行某个 Rust 测试。
- Tabnine:基于 AI 的自动补全,可以更快地撰写代码。
创建工程
- 使用 cargo new 工程名 创建一个工程
- 在Cargo.toml中添加依赖
- 运行cargo run或cargo build进行运行或者编译
小解释
- Cargo.toml 是 Rust 项目的配置管理文件,它符合 toml 的语法
- 函数体用花括号 {} 包裹
- 表达式之间用分号 ; 分隔,
- 访问结构体的成员函数或者变量使用点 . 运算符
- 访问命名空间(namespace)或者对象的静态函数使用双冒号 :: 运算符。
- 简化对命名空间内部的函数或者数据类型的引用,可以使用 use 关键字
- 可执行体的入口函数是 main()。
- Rust 的变量默认是不可变的,如果要修改变量的值,需要显式地使用 mut 关键字。
- 除了 let / static / const / fn 等少数语句外,Rust 绝大多数代码都是表达式(expression)。 所以 if / while / for / loop 都会返回一个值,函数最后一个表达式就是函数的返回值,这和函数式编程语言一致。
基本内容
基本语法和基础数据类型
变量和函数
- Rust 支持类型推导,在编译器能够推导类型的情况下,变量类型一般可以省略,但常量(const)和静态变量(static)必须声明类型
- 默认变量不可变
- 函数是一等公民,可以作为参数或者返回值 代码
- Rust 函数参数的类型和返回值的类型都必须显式定义,如果没有返回值可以省略,返回 unit。函数内部如果提前返回,需要用 return 关键字,否则最后一个表达式就是其返回值。如果最后一个表达式后添加了; 分号,隐含其返回值为 unit 代码
数据结构
- 用 struct 定义结构体,用 enum 定义标签联合体(tagged union)
- 用 impl 关键字为数据结构实现 trait
#[derive(Debug)]为数据结构实现了 Debug trait,提供了 debug 能力,这样可以通过 {:?},用 println! 打印出来。- 通过
{}来打印的话则需要实现std::fmt::Display - Clone 让数据结构可以被复制,而 Copy 则让数据结构可以在参数传递的时候自动按字节拷贝
总结
控制流程
顺序执行
顺序执行就是一行行代码往下执行。在执行的过程中,遇到函数,会发生函数调用。
函数调用是代码在执行过程中,调用另一个函数,跳入其上下文执行,直到返回
循环
支持死循环 loop、条件循环 while,以及对迭代器的循环 for。
循环可以通过 break 提前终止,或者 continue 来跳到下一轮循环
for 循环实际上只是一个语法糖,编译器会将其展开使用 loop 循环对迭代器进行循环访问,直至返回 None
分支跳转、模式匹配、错误跳转和异步跳转
- 分支跳转就是我们熟悉的 if/else;
- Rust 的模式匹配可以通过匹配表达式或者值的某部分的内容,来进行分支跳转;
- 在错误跳转中,当调用的函数返回错误时,Rust 会提前终止当前函数的执行,向上一层返回错误。
- 在 Rust 的异步跳转中 ,当 async 函数执行 await 时,程序当前上下文可能被阻塞,执行流程会跳转到另一个异步任务执行,直至 await 不再阻塞。
总结
模式匹配
Rust 的模式匹配可用于 struct / enum 中匹配部分或者全部内容
可以直接对 enum 内层的数据进行匹配并赋值
错误处理
把错误封装在 Result 类型中,同时提供了 ? 操作符来传播错误
Result 类型是一个泛型数据结构,T 代表成功执行返回的结果类型,E 代表错误类型
Rust 项目的组织
用 mod 来组织crate下的代码
- 在项目的入口文件 lib.rs / main.rs 里,用 mod 来声明要加载的其它模块代码文件
- 如果模块内容比较多,可以放在一个目录下,在该目录下放一个 mod.rs 引入该模块的其它文件
- 用 mod + 目录名引入这个模块
小解释
- 一个项目也被称为一个 crate
- crate 可以是可执行项目,也可以是一个库,我们可以用 cargo new -- lib 来创建一个库。
- 当 crate 里的代码改变时,这个 crate 需要被重新编译。
- 单元测试和集成测试的代码也会放在 crate 里
- Rust 的单元测试一般放在和被测代码相同的文件中,使用条件编译 #[cfg(test)] 来确保测试代码只在测试环境下编译
- 集成测试一般放在 tests 目录下,和 src 平行。和单元测试不同,集成测试只能测试 crate 下的公开接口,编译时编译成单独的可执行文件
- 使用 cargo test 运行测试用例
使用workspace组织多个crate代码
一个 workspace 可以包含一到多个 crates,当代码发生改变时,只有涉及的 crates 才需要重新编译
代码编译是以Crate为单位的
- 在某个目录下生成一个如图所示的 Cargo.toml,包含 workspace 里所有的 crates
- cargo new 生成对应的 crates
总结
好用链接
资料链接
精选问答
-
fn(i32) -> i32 这个类型是一个函数指针类型:doc.rust-lang.org/reference/t… a. 函数本身是一个指向 TEXT 段起始位置的指针