时间:2026-02-04 19:53
人气:
作者:admin
Rust工具: https://www.rust-lang.org/tools/install
cargo new my_test
开始于单元包的根节点:在编译一个单元包时,编译器会从单元包的根节点文件开始编译(通常是库单元包中的src/lib.rs,或二进制单元包中的src/main.rs)。
在 Rust 中,handle.join().unwrap() 是用于等待线程完成并获取其返回值的常见操作。
join() 方法返回一个 Result<T, Box<dyn Error>>,其中 T 是被等待线程的返回值类型。使用 unwrap() 是一种简单的错误处理方式,它会:
Ok(t),则返回内部的值 tErr(e),则会触发 panic 并显示错误信息fn main() {
// 创建一个线程并获取其句柄
let handle = thread::spawn(|| {
thread::sleep(Duration::from_secs(1));
"线程执行完成" // 线程的返回值
});
// 等待线程完成并获取返回值
let result = handle.join().unwrap();
println!("{}", result); // 输出: 线程执行完成
}
在 Rust 中,let _ = handle.join(); 是一种处理线程 JoinHandle 的方式,它的作用是:
join() 方法阻塞当前线程,等待被 spawn 的线程执行完成let _ = 忽略 join() 返回的 Result 值handle.join().unwrap() 不同,这种写法会静默忽略任何可能的错误,包括线程恐慌。curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
或者
wget --https-only --secure-protocol=TLSv1_2 -qO- https://sh.rustup.rs | sh
刷新环境变量
安装完成后,需要让终端识别新安装的 rustup 命令,执行:
source $HOME/.cargo/env
[22:35:07] root@ceph-221:/home/code/eza# curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
info: downloading installer
warn: It looks like you have an existing installation of Rust at:
warn: /usr/bin
warn: It is recommended that rustup be the primary Rust installation.
warn: Otherwise you may have confusion unless you are careful with your PATH.
warn: If you are sure that you want both rustup and your already installed Rust
warn: then please reply `y' or `yes' or set RUSTUP_INIT_SKIP_PATH_CHECK to yes
warn: or pass `-y' to ignore all ignorable checks.
error: cannot install while Rust is installed
解决方法:
这个错误是因为系统中已经通过包管理器(如 apt、yum 等)安装了 Rust,而 rustup 检测到了现有安装,为了避免环境冲突而终止了安装。解决方法如下:
为了让 rustup 成为主要的 Rust 工具链管理器,建议先卸载系统预装的 Rust:
sudo dnf remove rust cargo
卸载完成后,重新运行 rustup 安装脚本。
在 Rust 中,println!("{:?}", other); 是一个用于打印变量 other 调试信息的宏调用,其中 {:?} 是格式化占位符,对应 Debug 格式化输出。
{:?} 要求被打印的类型实现了标准库的 std::fmt::Debug trait,该 trait 用于提供类型的调试友好格式(通常包含详细的内部结构)。{}(对应 Display trait)不同,Debug 输出更偏向开发者调试,格式可能更冗长(例如包含字段名、引号等),且通常由编译器自动派生(通过 #[derive(Debug)]),无需手动实现。{:?} 的变体 {:#?} 会生成带缩进的多行格式,适合复杂结构(如嵌套的结构体、长列表):在Rust中,由Copy trait来区分值语义和引用语义。与此同时,Rust也引入了新的语义:复制(Copy)语义和移动(Move)语义。复制语义对应值语义,移动语义对应引用语义。
Rust的借用检查器(borrow checker),借用检查器会检查所有数据访问是否合法。借用检查依赖于3个紧密关联的概念:所有权、生命周期和借用。
所有权的特点:
生命周期参数的目的是帮助借用检查器验证合法的引用,消除悬垂指针
省略生命周期参数
对于Box<T>类型来说,如果包含的类型T属于复制语义,则执行按位复制;如果属于移动语义,则移动所有权
在 Rust 中,?Sized 是一个用于 trait bound 的特殊标记,用于表示“允许类型不实现 Sized trait”。要理解它,首先需要了解 Sized trait 本身:
Sized 是 Rust 中的一个自动实现的 trait,用于标记“在编译时已知大小的类型”(例如 i32、String、自定义结构体等)。
Sized,例如:
[T](长度未知,需通过 &[T] 等指针间接使用);dyn Trait,具体类型大小未知);str(长度未知,需通过 &str 使用)。?Sized 的作用:放宽 Sized 限制
Rust 中,泛型默认隐含 Sized 约束。例如:
fn foo<T>(x: T) { ... }
// 等价于
fn foo<T: Sized>(x: T) { ... }
这意味着泛型 T 只能接受编译时大小已知的类型(Sized 类型)。
而 ?Sized 的作用是取消这种默认约束,允许泛型接受“可能不实现 Sized 的类型”。例如:
fn bar<T: ?Sized>(x: &T) { ... }
这里 T 可以是 Sized 类型(如 i32),也可以是动态大小类型(如 str、dyn Trait)。
?Sized 通常用于需要处理动态大小类型的场景,常见情况:
接受 trait 对象:
trait 对象(dyn Trait)是 DST,因此泛型需要 ?Sized 才能接受它:
trait MyTrait { fn do_something(&self); }
// 允许 T 为 dyn MyTrait(DST)
fn call_trait<T: MyTrait + ?Sized>(x: &T) {
x.do_something();
}
// 使用:可以传入任何实现 MyTrait 的类型的引用,或 trait 对象
let obj: &dyn MyTrait = &SomeType;
call_trait(obj); // 合法
处理切片或字符串:
直接使用 [T] 或 str 时(通常通过引用):
// 接受 str(DST)的引用
fn print_str<T: ?Sized>(s: &T) where T: AsRef<str> {
println!("{}", s.as_ref());
}
print_str("hello"); // 字符串字面量是 &str,底层是 str(DST)
定义容纳 DST 的类型:
例如自定义智能指针时,指向 DST:
struct MyBox<T: ?Sized>(*const T);
impl<T: ?Sized> MyBox<T> {
fn new(x: &T) -> Self {
MyBox(x as *const T)
}
}
?Sized 仅用于泛型约束,不能直接修饰具体类型。?Sized 的泛型通常需要通过引用(&T) 或指针(如 Box<T>、Rc<T>) 间接操作。?Sized 是“允许不 Sized”,而非“必须不 Sized”,因此仍能接受 Sized 类型。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:简单轻量的实现,适合快速上手,无需复杂配置。Rust 日志库定义了 5 个标准级别(级别越高,输出日志越少):
trace:最详细的调试信息(如函数调用参数、循环步骤),通常用于开发阶段细粒度调试。debug:调试信息(如关键流程节点、变量值),适合开发和测试环境。info:普通运行信息(如程序启动、任务完成),生产环境常用。warn:警告信息(如不影响运行的异常情况,如“配置项缺失,使用默认值”)。error:错误信息(如功能失败、资源不可用),必须关注的问题。规则:设置某一级别后,会输出该级别及所有更高级别的日志。例如,RUST_LOG=info 会输出 info、warn、error 级别的日志。
通过 RUST_LOG=<级别> 控制全局日志输出:
# 只输出 error 及以上级别日志(最简洁)
RUST_LOG=error cargo run
# 输出 info 及以上级别(info, warn, error)
RUST_LOG=info ./my_rust_program
# 输出 debug 及以上级别(开发调试常用)
RUST_LOG=debug cargo test
# 输出所有级别(包括 trace,最详细)
RUST_LOG=trace ./my_rust_program
通过 RUST_LOG=<模块路径>=<级别> 只输出特定模块的日志,避免全局日志冗余:
# 只输出 my_project 中 network 模块的 debug 级别日志
RUST_LOG=my_project::network=debug cargo run
# 输出 tokio 库的 info 日志 + 自己代码的 debug 日志
RUST_LOG=tokio=info,my_project=debug ./my_program
# 禁用某个模块的日志(设置为 off)
RUST_LOG=my_project::legacy=off ./my_program
mod 结构(如 crate::utils::file)。tokio、hyper),控制其日志输出。用逗号分隔多个规则,实现精细化控制:
# 全局 info 级别,但 network 模块用 debug,tokio 库用 warn
RUST_LOG=info,my_project::network=debug,tokio=warn ./my_program
RUST_LOG需配合日志库(如 log + env_logger)在程序中初始化日志系统,才能让 RUST_LOG 生效。示例:
在 Cargo.toml 中添加依赖:
[dependencies]
log = "0.4" # 日志基础库
env_logger = "0.9" # 解析 RUST_LOG 的库
在代码中初始化:
use log::{info, debug, error};
fn main() {
// 初始化日志系统,读取 RUST_LOG 环境变量
env_logger::init();
info!("程序启动");
debug!("配置文件路径: ./config.toml"); // 仅 RUST_LOG>=debug 时输出
error!("数据库连接失败");
}
上一篇:再见 Postman!一款开源免费的全能 API 客户端工具
下一篇:没有了