RUST进阶

修改记录

version修改记录修改人修改时间
0.1初始版本linux-logic2025年2月9日

rust构建工具cargo

概述

在使用官方工具安装rust环境后,会有以下说明:

  • Rustup metadata and toolchains will be installed into the Rustup home directory, located at(This can be modified with the RUSTUP_HOME environment variable):
    • /home/linux-logic/.rustup
  • he Cargo home directory is located at(This can be modified with the CARGO_HOME environment variable.):
    • /home/linux-logic/.cargo
  • The cargo, rustc, rustup and other commands will be added to Cargo’s bin directory, located at:
    • /home/linux-logic/.cargo/bin
    • This path will then be added to your PATH environment variable by modifying the profile files located at:
      • /home/linux-logic/.profile
      • /home/linux-logic/.bashrc

其中会安装cargo工具用于管理rust环境。简而言之,cargo是一个编译+包管理工具,可以借助此工具管理工具链、相关环境变量、自动生成源码模板等。个人理解,在编译情况下,cargo与rust,类比于make与c。

Cargo-编译与运行

检查

在执行以下命令时,可仅检查可编译情况,但不会进行实际编译。此动作远快于build命令。

cargo check

编译

rustc命令的封装。在执行cargo build后,会自动生成可执行文件到:

target/debug/hello_world

同时会自动生成Cargo.lock文件,用于记录当前所依赖的库的版本号

运行

在执行以下命令时,可以直接运行当前源码环境中的可执行程序。由于当源码环境发生变化时,此命令会重新触发编译,因此可直接运行此命令进行编译&运行。

cargo run // 用于生成debug版本程序
cargo run --release // 用于生成正式版本程序

需要注意,以上两个命令针对不同的使用场景:

  • debug:编译速度较快,运行速度较慢。一般用于调试阶段。
  • release:编译速度较慢,但运行速度较快,一般运用正式发布。

库的使用

rust标准库分为两种类型:

  • 一种叫做the prelude:这类库默认被导入,无需显示引用。
  • 一种叫做other preludes:这类库需要自己显示引用。

不同版本the prelude包含的具体的库,可参考官方链接:>https://doc.rust-lang.org/stable/std/prelude/index.html

Crate

Crate是Rust中的一个亮点。一个Crate就是一堆源码文件的集合,分为:

  • binary crate:二进制的crate,是一个可以直接执行的二进制文件
  • library crate:库的crate,用于提供某些特定的功能函数,但本身不可以直接运行
    某些功能可能不在rust标准库中,此时我们就可以引用Crate。

如何使用Crate

当需要使用某个crate时,需要修改Cargo.toml文件,增加相关的crate的包名,以及对应的版本号:

[dependencies]
rand = "0.8.5"

重新编译时,可自动下载相关的包的代码:

linux-logic@logic:~/workspace/rust_workspace/guessing_game$ cargo build
    Blocking waiting for file lock on package cache
    Blocking waiting for file lock on package cache
    Blocking waiting for file lock on package cache
    Blocking waiting for file lock on package cache
   Compiling proc-macro2 v1.0.93
   Compiling unicode-ident v1.0.16
   Compiling libc v0.2.169
   Compiling byteorder v1.5.0
   Compiling cfg-if v1.0.0
   Compiling getrandom v0.2.15
   Compiling quote v1.0.38
   Compiling rand_core v0.6.4
   Compiling syn v2.0.98
   Compiling zerocopy-derive v0.7.35
   Compiling zerocopy v0.7.35
   Compiling ppv-lite86 v0.2.20
   Compiling rand_chacha v0.3.1
   Compiling rand v0.8.5
   Compiling guessing_game v0.1.0 (/home/linux-logic/workspace/rust_workspace/guessing_game)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 10m 34s

异常处理

RUST中,一般情况下,函数在正常返回结果的同时,会返回函数是否执行成功。“是否执行成功”一般都会使用Result(enum枚举类型)。该变量有:Ok和Err。如果是Err,则会同时返回相应的具体错误描述。一个典型的例子:

let guess: u32 = match guess.trim().parse() {
    Ok(num) => num,
    Err(_) => continue // 其中_表示匹配任何信息
};

同时,Result变量也包含了一些特殊方法,例如expect函数,此函数会捕获错误情况,然后让程序停下,并打印你指定的信息。例如:

io::stdin()
    .read_line(&mut guess)
    .expect("failed to read line");

RUST基本元素

变量

使用let关键词修饰。

默认情况下,RUST中的变量是不可变的,这其实意味着,RUST更推荐使用不可变的变量。当我们试图更改这种可不变变量时,RUST会触发编译错误。RUST的这种编译报错机制,可以避免某些难为排查的错误,例如有两个地方会更改变量值,当第二段代码仅仅在某些情况下会修改值,那么第一个地方可能会出现不可预测的错误。(不是特别理解,先放在这里@TODO)
当然,rust也允许变量变为可变的,即可以使用mut关键字,例如:

let mut x = 5;

变量的shadowing(翻译为”遮蔽“?)

rust允许重复声明变量,而第二次声明的变量会覆盖掉第一个声明的变量。例如:

fn main() {
    let x = 5;
    let x = x + 1;
    {
        let x = x * 2;
        println!("The value of x in the inner scope is: {x}");
    }
    println!("The value of x is: {x}"); }

运行结果如下:

The value of x in the inner scope is: 12  
The value of x is: 6

可以看到上述代码中,x这个变量被连续“遮蔽”了2次。但这里需要注意,“遮蔽”的动作和作用域有关,因为“遮蔽”是基于变量的声明动作,而变量的声明即伴随着作用域。
变量的shadowing与mut很像,但也有一些区别:

  • 当使用shadowing时,变量本质上还是不可变的,因此如果没有let关键字而尝试直接修改变量,就会导致编译失败。
  • 当使用shadowing时,本质上是重新声明了一个变量,因此可以更改变量的类型,例如从数字变为字符串。

常量

使用const关键词修饰。Rust 对常量的命名约定是要求单词大写,写之间使用下划线。

常量与变量存在以下区别:

  • constants常量永远是不可变的,不能使用mut关键词修饰
  • constants常量必须说明类型。

数据类型

RUST包含的数据类型有:

`i32`, a 32-bit number; `u32`, an unsigned 32-bit number; `i64`, a 64-bit number;

RUST有类型自动推导行为。例如,当运行如下代码:

let secret_number = rand::thread_rng().gen_range(1..=100);

此时会默认为i32类型;

帮助文档

可执行以下指令自动生成当前二进制的帮助文档:

cargo doc --open

此命令生成的文档同时包括了当前二进制中使用到的库的帮助文档。
除此之外,可以阅读各类库的官方说明网站。这里列举了部分库的网站:

  • random:>https://rust-random.github.io/book/

参考链接

https://doc.rust-lang.org/stable/book/title-page.html