找回密码
 立即注册
首页 业界区 安全 Rust简要汇总(持续更新)

Rust简要汇总(持续更新)

扔飒 2026-2-4 20:50:02
Rust工具: https://www.rust-lang.org/tools/install
1 cargo
  1. cargo new my_test
复制代码
开始于单元包的根节点:在编译一个单元包时,编译器会从单元包的根节点文件开始编译(通常是库单元包中的src/lib.rs,或二进制单元包中的src/main.rs)​。
2 thread

在 Rust 中,handle.join().unwrap() 是用于等待线程完成并获取其返回值的常见操作。
join() 方法返回一个 Result,其中 T 是被等待线程的返回值类型。使用 unwrap() 是一种简单的错误处理方式,它会:

  • 如果结果是 Ok(t),则返回内部的值 t
  • 如果结果是 Err(e),则会触发 panic 并显示错误信息
  1. fn main() {
  2.     // 创建一个线程并获取其句柄
  3.     let handle = thread::spawn(|| {
  4.         thread::sleep(Duration::from_secs(1));
  5.         "线程执行完成" // 线程的返回值
  6.     });
  7.     // 等待线程完成并获取返回值
  8.     let result = handle.join().unwrap();
  9.     println!("{}", result); // 输出: 线程执行完成
  10. }
复制代码
在 Rust 中,let _ = handle.join(); 是一种处理线程 JoinHandle 的方式,它的作用是:

  • 调用 join() 方法阻塞当前线程,等待被 spawn 的线程执行完成
  • 使用 let _ = 忽略 join() 返回的 Result 值
    与 handle.join().unwrap() 不同,这种写法会静默忽略任何可能的错误,包括线程恐慌。
3 安装
  1. curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
复制代码
或者
  1. wget --https-only --secure-protocol=TLSv1_2 -qO- https://sh.rustup.rs | sh
复制代码
刷新环境变量
安装完成后,需要让终端识别新安装的 rustup 命令,执行:
  1. source $HOME/.cargo/env
复制代码
3.1 问题


  • 安装rustup时报错:
  1. [22:35:07] root@ceph-221:/home/code/eza# curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  2. info: downloading installer
  3. warn: It looks like you have an existing installation of Rust at:
  4. warn: /usr/bin
  5. warn: It is recommended that rustup be the primary Rust installation.
  6. warn: Otherwise you may have confusion unless you are careful with your PATH.
  7. warn: If you are sure that you want both rustup and your already installed Rust
  8. warn: then please reply `y' or `yes' or set RUSTUP_INIT_SKIP_PATH_CHECK to yes
  9. warn: or pass `-y' to ignore all ignorable checks.
  10. error: cannot install while Rust is installed
复制代码
解决方法:
这个错误是因为系统中已经通过包管理器(如 apt、yum 等)安装了 Rust,而 rustup 检测到了现有安装,为了避免环境冲突而终止了安装。解决方法如下:
为了让 rustup 成为主要的 Rust 工具链管理器,建议先卸载系统预装的 Rust:
  1. sudo dnf remove rust cargo
复制代码
卸载完成后,重新运行 rustup 安装脚本。
4 格式化输出

在 Rust 中,println!("{:?}", other); 是一个用于打印变量 other 调试信息的宏调用,其中 {:?} 是格式化占位符,对应 Debug 格式化输出
4.1.1 核心作用


  • {:?} 要求被打印的类型实现了标准库的 std::fmt:ebug trait,该 trait 用于提供类型的调试友好格式(通常包含详细的内部结构)。
  • 与 {}(对应 Display trait)不同,Debug 输出更偏向开发者调试,格式可能更冗长(例如包含字段名、引号等),且通常由编译器自动派生(通过 #[derive(Debug)]),无需手动实现。
  • {:?} 的变体 {:#?} 会生成带缩进的多行格式,适合复杂结构(如嵌套的结构体、长列表):
5 所有权

在Rust中,由Copy trait来区分值语义和引用语义。与此同时,Rust也引入了新的语义:复制(Copy)语义和移动(Move)语义。复制语义对应值语义,移动语义对应引用语义。
Rust的借用检查器(borrow checker),借用检查器会检查所有数据访问是否合法。借用检查依赖于3个紧密关联的概念:所有权、生命周期和借用。

  • 所有权(ownership)是一个引申而来的比喻,在Rust中,所有权与针对不再需要的值的清理有关。
  • 值的生命周期是一个时间段,在此时间段内对该值的访问是有效的行为。
  • 借用一个值意味着要访问它。
所有权的特点:

  • 控制资源(不仅仅是内存)的释放
  • 出借所有权,包括不可变(共享)和可变(独占)的

    • 通过使用&操作完成所有权租借
    • 在不可变借用期间,所有者不能修改资源,也不能在进行可变借用
    • 在可变借用期间,所有者不能访问资源,并且也不能再出借所有权
    • 不可变借用可以出借多次,因为他不能修改内存数据;可变借用只能出借一次,否则难以预料数据何时何地被修改。

  • 转移所有权
生命周期参数的目的是帮助借用检查器验证合法的引用,消除悬垂指针

  • 借用的生命周期不能长于出借方的生命周期
  • 结构体实例的生命周期应短于或等于任意一个成员的生命周期
省略生命周期参数

  • 每个输入位置上省略的生命周期都将成为一个不同的生命周期参数
  • 如果只有一个输入生命周期的位置(不管是否忽略),则该生命周期都将分配给输出生命周期
  • 如果存在多个输入生命周期的位置,但是其中包含着&self或&mut self,则self的生命周期都将分配给输出生命周期
对于Box<T>类型来说,如果包含的类型T属于复制语义,则执行按位复制;如果属于移动语义,则移动所有权
6 类型

6.1 ?Sized

在 Rust 中,?Sized 是一个用于 trait bound 的特殊标记,用于表示“允许类型不实现 Sized trait”。要理解它,首先需要了解 Sized trait 本身:
6.1.1 Sized trait 是什么?

Sized 是 Rust 中的一个自动实现的 trait,用于标记“在编译时已知大小的类型”(例如 i32、String、自定义结构体等)。

  • 对于这类类型,编译器知道它们在内存中占据的精确大小,因此可以直接在栈上分配,也能作为函数参数/返回值直接传递。
  • 反之,动态大小类型(DST,Dynamically Sized Type) 则不实现 Sized,例如:

    • 切片 [T](长度未知,需通过 &[T] 等指针间接使用);
    • trait 对象(如 dyn Trait,具体类型大小未知);
    • 字符串字面量的底层类型 str(长度未知,需通过 &str 使用)。

?Sized 的作用:放宽 Sized 限制
Rust 中,泛型默认隐含 Sized 约束。例如:
  1. fn foo<T>(x: T) { ... }
  2. // 等价于
  3. fn foo<T: Sized>(x: T) { ... }
复制代码
这意味着泛型 T 只能接受编译时大小已知的类型(Sized 类型)。
而 ?Sized 的作用是取消这种默认约束,允许泛型接受“可能不实现 Sized 的类型”。例如:
  1. fn bar<T: ?Sized>(x: &T) { ... }
复制代码
这里 T 可以是 Sized 类型(如 i32),也可以是动态大小类型(如 str、dyn Trait)。
6.1.2 使用场景

?Sized 通常用于需要处理动态大小类型的场景,常见情况:

  • 接受 trait 对象
    trait 对象(dyn Trait)是 DST,因此泛型需要 ?Sized 才能接受它:
    1. trait MyTrait { fn do_something(&self); }
    2. // 允许 T 为 dyn MyTrait(DST)
    3. fn call_trait<T: MyTrait + ?Sized>(x: &T) {
    4.     x.do_something();
    5. }
    6. // 使用:可以传入任何实现 MyTrait 的类型的引用,或 trait 对象
    7. let obj: &dyn MyTrait = &SomeType;
    8. call_trait(obj); // 合法
    复制代码
  • 处理切片或字符串
    直接使用 [T] 或 str 时(通常通过引用):
    1. // 接受 str(DST)的引用
    2. fn print_str<T: ?Sized>(s: &T) where T: AsRef<str> {
    3.     println!("{}", s.as_ref());
    4. }
    5. print_str("hello"); // 字符串字面量是 &str,底层是 str(DST)
    复制代码
  • 定义容纳 DST 的类型
    例如自定义智能指针时,指向 DST:
    1. struct MyBox<T: ?Sized>(*const T);
    2. impl<T: ?Sized> MyBox<T> {
    3.     fn new(x: &T) -> Self {
    4.         MyBox(x as *const T)
    5.     }
    6. }
    复制代码
6.1.3 注意点


  • ?Sized 仅用于泛型约束,不能直接修饰具体类型。
  • 由于 DST 无法在栈上直接存储或作为值传递,使用 ?Sized 的泛型通常需要通过引用(&T)指针(如 Box、Rc) 间接操作。
  • ?Sized 是“允许不 Sized”,而非“必须不 Sized”,因此仍能接受 Sized 类型。
7 log

RUST_LOG 是 Rust 生态中用于控制 日志输出 的环境变量,主要配合 Rust 的日志库(如 log、tracing)使用,用于动态调整日志的 级别模块范围输出内容,无需修改代码即可灵活控制程序的日志行为。
log是Rust 生态中最基础、应用最广泛的 日志抽象库(crate),它本身不直接实现日志的输出功能,而是定义了一套统一的日志接口(如日志级别、宏定义),让其他库或应用可以基于这套接口实现日志记录,同时保证不同日志实现之间的兼容性

  • 提供统一的日志接口
    定义了 trace!、debug!、info!、warn!、error! 等日志宏,以及 Log、Level、Metadata 等核心 trait 和枚举,让开发者可以用一致的方式编写日志代码,无需关心底层如何输出(如打印到终端、写入文件、发送到日志服务器等)。
  • 解耦日志生产与消费
    库开发者只需依赖 log 库编写日志(如 info!("初始化完成")),而应用开发者可以自由选择日志的实现方式(如 env_logger、tracing、fern 等),两者通过 log 的接口对接,避免了库与特定日志实现的强耦合。
  • 常用搭配的日志实现库
    log 库本身不输出日志,必须配合具体的 “日志实现库” 才能生效,常见的有:

    • env_logger:通过 RUST_LOG 环境变量控制日志输出,适合命令行工具和开发调试。
    • tracing:更强大的日志和追踪库,支持结构化日志、跨度(span)追踪,适合复杂应用和分布式系统。
    • fern:支持将日志输出到文件、终端等多种目标,可自定义格式和滚动策略。
    • simple_logger:简单轻量的实现,适合快速上手,无需复杂配置。

7.1 日志级别(从低到高)

Rust 日志库定义了 5 个标准级别(级别越高,输出日志越少):

  • trace:最详细的调试信息(如函数调用参数、循环步骤),通常用于开发阶段细粒度调试。
  • debug:调试信息(如关键流程节点、变量值),适合开发和测试环境。
  • info:普通运行信息(如程序启动、任务完成),生产环境常用。
  • warn:警告信息(如不影响运行的异常情况,如“配置项缺失,使用默认值”)。
  • error:错误信息(如功能失败、资源不可用),必须关注的问题。
规则:设置某一级别后,会输出该级别及所有更高级别的日志。例如,RUST_LOG=info 会输出 info、warn、error 级别的日志。
7.2 基本设置方法

7.2.1 全局设置日志级别

通过 RUST_LOG= 控制全局日志输出:
  1. # 只输出 error 及以上级别日志(最简洁)
  2. RUST_LOG=error cargo run
  3. # 输出 info 及以上级别(info, warn, error)
  4. RUST_LOG=info ./my_rust_program
  5. # 输出 debug 及以上级别(开发调试常用)
  6. RUST_LOG=debug cargo test
  7. # 输出所有级别(包括 trace,最详细)
  8. RUST_LOG=trace ./my_rust_program
复制代码
7.2.2 限定模块/ crate 的日志范围

通过 RUST_LOG== 只输出特定模块的日志,避免全局日志冗余:
  1. # 只输出 my_project 中 network 模块的 debug 级别日志
  2. RUST_LOG=my_project::network=debug cargo run
  3. # 输出 tokio 库的 info 日志 + 自己代码的 debug 日志
  4. RUST_LOG=tokio=info,my_project=debug ./my_program
  5. # 禁用某个模块的日志(设置为 off)
  6. RUST_LOG=my_project::legacy=off ./my_program
复制代码

  • 模块路径对应代码中的 mod 结构(如 crate::utils::file)。
  • 可以指定第三方 crate 的名称(如 tokio、hyper),控制其日志输出。
7.2.3 组合设置(多模块 + 不同级别)

用逗号分隔多个规则,实现精细化控制:
  1. # 全局 info 级别,但 network 模块用 debug,tokio 库用 warn
  2. RUST_LOG=info,my_project::network=debug,tokio=warn ./my_program
复制代码
7.2.4 在代码中读取 RUST_LOG

需配合日志库(如 log + env_logger)在程序中初始化日志系统,才能让 RUST_LOG 生效。示例:

  • 在 Cargo.toml 中添加依赖:
    1. [dependencies]
    2. log = "0.4"          # 日志基础库
    3. env_logger = "0.9"   # 解析 RUST_LOG 的库
    复制代码
  • 在代码中初始化:
    1. use log::{info, debug, error};
    2. fn main() {
    3.     // 初始化日志系统,读取 RUST_LOG 环境变量
    4.     env_logger::init();
    5.     info!("程序启动");
    6.     debug!("配置文件路径: ./config.toml");  // 仅 RUST_LOG>=debug 时输出
    7.     error!("数据库连接失败");
    8. }
    复制代码

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

2026-2-6 06:53:38

举报

2026-2-7 22:52:52

举报

懂技术并乐意极积无私分享的人越来越少。珍惜
2026-2-8 16:23:06

举报

2026-2-10 13:07:16

举报

前天 10:15

举报

您需要登录后才可以回帖 登录 | 立即注册