03|初窥门径:从你的第一个Rust程序开始!

206 阅读5分钟

正式开始

安装

安装链接

VS常用的Rust插件

  1. rust-analyzer:实时编译和分析 Rust 代码,提示代码中的错误,并对类型进行标注。
  2. rust syntax:为代码提供语法高亮。
  3. crates:分析当前项目的依赖是否是最新的版本。
  4. better toml:Rust 使用 toml 做项目的配置管理。better toml 可以语法高亮,并展示 toml 文件中的错误。
  5. rust test lens:快速运行某个 Rust 测试。
  6. Tabnine:基于 AI 的自动补全,可以更快地撰写代码。

创建工程

  1. 使用 cargo new 工程名 创建一个工程
  2. 在Cargo.toml中添加依赖
  3. 运行cargo run或cargo build进行运行或者编译

小解释

  1. Cargo.toml 是 Rust 项目的配置管理文件,它符合 toml 的语法
  2. 函数体用花括号 {} 包裹
  3. 表达式之间用分号 ; 分隔,
  4. 访问结构体的成员函数或者变量使用点 . 运算符
  5. 访问命名空间(namespace)或者对象的静态函数使用双冒号 :: 运算符。
  6. 简化对命名空间内部的函数或者数据类型的引用,可以使用 use 关键字
  7. 可执行体的入口函数是 main()。
  8. Rust 的变量默认是不可变的,如果要修改变量的值,需要显式地使用 mut 关键字。
  9. 除了 let / static / const / fn 等少数语句外,Rust 绝大多数代码都是表达式(expression)。 所以 if / while / for / loop 都会返回一个值,函数最后一个表达式就是函数的返回值,这和函数式编程语言一致。

基本内容

image.png

基本语法和基础数据类型

变量和函数

  1. Rust 支持类型推导,在编译器能够推导类型的情况下,变量类型一般可以省略,但常量(const)和静态变量(static)必须声明类型
  2. 默认变量不可变
  3. 函数是一等公民,可以作为参数或者返回值 代码
  4. Rust 函数参数的类型和返回值的类型都必须显式定义,如果没有返回值可以省略,返回 unit。函数内部如果提前返回,需要用 return 关键字,否则最后一个表达式就是其返回值。如果最后一个表达式后添加了; 分号,隐含其返回值为 unit 代码

数据结构

  1. 用 struct 定义结构体,用 enum 定义标签联合体(tagged union)
  2. 用 impl 关键字为数据结构实现 trait
  3. #[derive(Debug)] 为数据结构实现了 Debug trait,提供了 debug 能力,这样可以通过 {:?},用 println! 打印出来。
  4. 通过{}来打印的话则需要实现std::fmt::Display
  5. Clone 让数据结构可以被复制,而 Copy 则让数据结构可以在参数传递的时候自动按字节拷贝

总结

image.png

控制流程

顺序执行

顺序执行就是一行行代码往下执行。在执行的过程中,遇到函数,会发生函数调用。

函数调用是代码在执行过程中,调用另一个函数,跳入其上下文执行,直到返回

循环

支持死循环 loop、条件循环 while,以及对迭代器的循环 for。

循环可以通过 break 提前终止,或者 continue 来跳到下一轮循环

for 循环实际上只是一个语法糖,编译器会将其展开使用 loop 循环对迭代器进行循环访问,直至返回 None

分支跳转、模式匹配、错误跳转和异步跳转

  1. 分支跳转就是我们熟悉的 if/else;
  2. Rust 的模式匹配可以通过匹配表达式或者值的某部分的内容,来进行分支跳转;
  3. 在错误跳转中,当调用的函数返回错误时,Rust 会提前终止当前函数的执行,向上一层返回错误。
  4. 在 Rust 的异步跳转中 ,当 async 函数执行 await 时,程序当前上下文可能被阻塞,执行流程会跳转到另一个异步任务执行,直至 await 不再阻塞。

总结

image.png

模式匹配

Rust 的模式匹配可用于 struct / enum 中匹配部分或者全部内容

可以直接对 enum 内层的数据进行匹配并赋值

错误处理

把错误封装在 Result 类型中,同时提供了 ? 操作符来传播错误

Result 类型是一个泛型数据结构,T 代表成功执行返回的结果类型,E 代表错误类型

Rust 项目的组织

用 mod 来组织crate下的代码

  1. 在项目的入口文件 lib.rs / main.rs 里,用 mod 来声明要加载的其它模块代码文件
  2. 如果模块内容比较多,可以放在一个目录下,在该目录下放一个 mod.rs 引入该模块的其它文件
  3. 用 mod + 目录名引入这个模块

image.png

小解释

  1. 一个项目也被称为一个 crate
  2. crate 可以是可执行项目,也可以是一个库,我们可以用 cargo new -- lib 来创建一个库。
  3. 当 crate 里的代码改变时,这个 crate 需要被重新编译。
  4. 单元测试和集成测试的代码也会放在 crate 里
  5. Rust 的单元测试一般放在和被测代码相同的文件中,使用条件编译 #[cfg(test)] 来确保测试代码只在测试环境下编译
  6. 集成测试一般放在 tests 目录下,和 src 平行。和单元测试不同,集成测试只能测试 crate 下的公开接口,编译时编译成单独的可执行文件
  7. 使用 cargo test 运行测试用例

使用workspace组织多个crate代码

一个 workspace 可以包含一到多个 crates,当代码发生改变时,只有涉及的 crates 才需要重新编译

代码编译是以Crate为单位的

  1. 在某个目录下生成一个如图所示的 Cargo.toml,包含 workspace 里所有的 crates
  2. cargo new 生成对应的 crates

image.png

总结

image.png

好用链接

  1. Rust Playground
  2. 第一个HelloWorld程序
  3. HTTP客户端框架 reqwest

资料链接

  1. Toml 语法
  2. static 关键字
  3. lazy static开源库
  4. unit类型
  5. 怎么写测试

精选问答

  1. fn(i32) -> i32 这个类型是一个函数指针类型:doc.rust-lang.org/reference/t… a. 函数本身是一个指向 TEXT 段起始位置的指针