
文章目录
- [第2章 第一个Rust程序](#第2章 第一个Rust程序)
-
- [2.1 Hello World程序详解](#2.1 Hello World程序详解)
-
- [2.1.1 传统的Hello World程序](#2.1.1 传统的Hello World程序)
- [2.1.2 深入理解println!宏](#2.1.2 深入理解println!宏)
- [2.1.3 编译和运行过程详解](#2.1.3 编译和运行过程详解)
- [2.1.4 理解Rust的编译错误](#2.1.4 理解Rust的编译错误)
- [2.2 Cargo包管理器入门](#2.2 Cargo包管理器入门)
-
- [2.2.1 Cargo项目结构详解](#2.2.1 Cargo项目结构详解)
- [2.2.2 深入Cargo.toml配置](#2.2.2 深入Cargo.toml配置)
- [2.2.3 Cargo命令大全](#2.2.3 Cargo命令大全)
- [2.2.4 创建多二进制项目](#2.2.4 创建多二进制项目)
- [2.2.5 构建脚本和自定义构建](#2.2.5 构建脚本和自定义构建)
- [2.3 代码组织结构](#2.3 代码组织结构)
-
- [2.3.1 模块系统深度解析](#2.3.1 模块系统深度解析)
- [2.3.2 可见性和访问控制](#2.3.2 可见性和访问控制)
- [2.4 基础调试技巧](#2.4 基础调试技巧)
-
- [2.4.1 打印调试技术](#2.4.1 打印调试技术)
- [2.4.2 断言和调试断言](#2.4.2 断言和调试断言)
- [2.4.3 日志系统集成](#2.4.3 日志系统集成)
- [2.4.4 调试器集成](#2.4.4 调试器集成)
- [2.4.5 性能调试和分析](#2.4.5 性能调试和分析)
- [2.4.6 错误处理和调试](#2.4.6 错误处理和调试)
第2章 第一个Rust程序
2.1 Hello World程序详解
2.1.1 传统的Hello World程序
让我们从最基础的Rust程序开始,深入了解每个组成部分:
rust
// 这是main函数 - 程序的入口点
fn main() {
// 这是一个宏调用,用于向标准输出打印文本
println!("Hello, World!");
// 让我们添加一些额外的打印来理解程序流程
println!("程序开始执行...");
print_message();
println!("程序执行完毕!");
}
// 定义一个辅助函数
fn print_message() {
println!("这是从函数中打印的消息!");
println!("Rust程序的基本结构:");
println!("1. 使用fn关键字定义函数");
println!("2. main函数是程序入口");
println!("3. 语句以分号结尾");
println!("4. 使用println!宏进行输出");
}
代码分析详解:
-
注释系统:
- 单行注释:
// 注释内容 - 文档注释:
/// 文档注释(用于生成文档)
- 单行注释:
-
函数定义:
fn关键字用于声明函数main函数是特殊的入口函数,没有参数和返回值- 函数体由大括号
{}包围
-
宏调用:
println!是一个宏(注意!符号)- 宏在编译时展开,提供强大的元编程能力
- 字符串字面量用双引号包围
2.1.2 深入理解println!宏
println!宏远比表面看起来强大,让我们探索其各种用法:
rust
fn detailed_print_examples() {
// 基础字符串打印
println!("简单的字符串打印");
// 位置参数
println!("{0},这是{1}。{1}很有趣!", "你好", "Rust");
// 命名参数
println!("{name}今年{age}岁", name = "小明", age = 25);
// 格式化数字
let pi = 3.1415926;
println!("π的值是: {:.2}", pi); // 保留两位小数
println!("二进制: {:b}, 十六进制: {:x}", 255, 255);
// 对齐和填充
println!("左对齐: {:<10}", "文本");
println!("右对齐: {:>10}", "文本");
println!("居中对齐: {:^10}", "文本");
println!("带填充: {:*^10}", "文本");
// 调试打印
let complex_data = vec!["apple", "banana", "cherry"];
println!("调试视图: {:?}", complex_data);
println!("美化调试: {:#?}", complex_data);
// 表达式求值
println!("计算结果是: {}", 5 * 3 + 2);
// 多行字符串
println!("
这是一个
多行
字符串
");
}
2.1.3 编译和运行过程详解
让我们深入了解Rust程序的编译和执行过程:
rust
// 预处理指令(属性)
#![allow(unused_variables)] // 允许未使用的变量警告
/// 这个函数演示了Rust的编译时检查
fn compile_time_checks() {
// 类型检查
let x: i32 = 42; // 明确的类型注解
let y = 3.14; // 类型推断
// 所有权检查
let s1 = String::from("hello");
let s2 = s1; // 所有权转移
// println!("{}", s1); // 这行会编译错误!
// 借用检查
let mut data = vec![1, 2, 3];
let reference = &data[0]; // 不可变借用
// data.push(4); // 这行会编译错误!不能同时存在可变和不可变借用
println!("引用: {}", reference);
}
fn main() {
println!("=== Rust程序执行流程 ===");
// 1. 程序启动
println!("1. 程序启动,main函数被调用");
// 2. 栈内存分配
let stack_variable = 100;
println!("2. 栈变量创建: {}", stack_variable);
// 3. 堆内存分配
let heap_variable = String::from("堆上的字符串");
println!("3. 堆变量创建: {}", heap_variable);
// 4. 函数调用
nested_function();
// 5. 作用域结束,资源清理
println!("5. main函数即将结束,自动清理资源");
}
fn nested_function() {
println!("4. 进入嵌套函数");
let local_var = "局部变量";
println!(" 在函数内创建: {}", local_var);
println!(" 函数结束,局部变量被清理");
}
2.1.4 理解Rust的编译错误
Rust编译器以提供有用的错误信息而闻名。让我们故意制造一些错误来理解编译器的工作方式:
rust
fn understanding_compiler_errors() {
// 取消下面的注释来查看各种编译错误
// 错误1: 类型不匹配
// let x: i32 = "hello"; // 期望i32,找到&str
// 错误2: 使用未初始化的变量
// let y: i32;
// println!("{}", y); // 使用了可能未初始化的变量
// 错误3: 所有权错误
// let s1 = String::from("text");
// let s2 = s1;
// println!("{}", s1); // s1的所有权已移动
// 错误4: 借用规则违反
// let mut v = vec![1, 2, 3];
// let first = &v[0];
// v.push(4); // 不能可变借用,因为已有不可变借用
println!("如果上面的注释被取消,编译将会失败");
}
2.2 Cargo包管理器入门
2.2.1 Cargo项目结构详解
让我们深入了解Cargo创建的完整项目结构:
bash
# 创建新项目
cargo new comprehensive_hello --bin
cd comprehensive_hello
项目结构分析:
comprehensive_hello/
├── Cargo.toml # 项目配置和依赖管理
├── Cargo.lock # 精确的依赖版本锁定(自动生成)
├── .gitignore # Git忽略文件配置
├── .cargo/ # Cargo配置目录
│ └── config.toml # 本地Cargo配置
└── src/
├── main.rs # 主程序入口
├── lib.rs # 库代码(如果存在)
├── bin/ # 额外的二进制目标
│ ├── helper1.rs
│ └── helper2.rs
└── utils/ # 工具模块
├── mod.rs
└── math.rs
2.2.2 深入Cargo.toml配置
让我们创建一个功能完整的Cargo.toml文件:
toml
[package]
name = "comprehensive_hello"
version = "0.1.0"
authors = ["你的名字 <email@example.com>"]
edition = "2021"
description = "一个全面的Rust Hello World示例"
license = "MIT OR Apache-2.0"
readme = "README.md"
homepage = "https://github.com/username/comprehensive_hello"
repository = "https://github.com/username/comprehensive_hello"
keywords = ["hello", "example", "learning"]
categories = ["command-line-utilities"]
# 参见更多键及其定义:https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
# 标准库依赖(隐式包含)
# 外部crate依赖
chrono = { version = "0.4", features = ["serde"] }
rand = "0.8.5"
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.0", features = ["full"] }
[dev-dependencies]
# 开发时依赖(测试、示例、基准测试)
assert_cmd = "2.0"
tempfile = "3.3"
[build-dependencies]
# 构建脚本依赖
cc = "1.0"
[features]
# 条件编译特性
default = ["logging", "network"]
logging = ["dep:log", "dep:env_logger"] # 显式特性依赖
network = ["dep:reqwest"]
advanced = []
[[bin]]
name = "comprehensive_hello"
path = "src/main.rs"
[[bin]]
name = "helper_tool"
path = "src/bin/helper1.rs"
[profile.dev]
opt-level = 0
debug = true
debug-assertions = true
overflow-checks = true
lto = false
panic = 'unwind'
incremental = true
codegen-units = 256
rpath = false
[profile.release]
opt-level = 3
debug = false
debug-assertions = false
overflow-checks = false
lto = true
panic = 'abort'
incremental = false
codegen-units = 1
rpath = false
[workspace]
# 工作区配置(对于更大的项目)
# members = ["crates/*"]
2.2.3 Cargo命令大全
让我们探索Cargo的各种命令和用法:
rust
// src/main.rs - 主程序文件
use std::process::Command;
fn main() {
println!("=== Cargo 命令演示 ===");
// 模拟各种Cargo命令的使用场景
demonstrate_cargo_commands();
// 构建配置示例
build_configuration_example();
}
fn demonstrate_cargo_commands() {
println!("\n1. 基础构建命令:");
println!(" cargo build - 开发构建");
println!(" cargo build --release - 发布构建");
println!(" cargo check - 快速编译检查");
println!(" cargo run - 编译并运行");
println!(" cargo clean - 清理构建产物");
println!("\n2. 依赖管理命令:");
println!(" cargo add <crate> - 添加依赖");
println!(" cargo update - 更新依赖");
println!(" cargo tree - 显示依赖树");
println!(" cargo search <term> - 搜索crate");
println!("\n3. 测试和检查命令:");
println!(" cargo test - 运行测试");
println!(" cargo bench - 运行基准测试");
println!(" cargo doc - 生成文档");
println!(" cargo doc --open - 生成并打开文档");
println!(" cargo fmt - 代码格式化");
println!(" cargo clippy - 代码检查");
println!("\n4. 发布和分发命令:");
println!(" cargo publish - 发布到crates.io");
println!(" cargo install <crate> - 安装二进制crate");
println!(" cargo uninstall <crate> - 卸载二进制crate");
}
fn build_configuration_example() {
println!("\n=== 构建配置示例 ===");
// 条件编译示例
#[cfg(debug_assertions)]
println!("当前是调试构建");
#[cfg(not(debug_assertions))]
println!("当前是发布构建");
// 特性标志示例
#[cfg(feature = "logging")]
println!("日志特性已启用");
#[cfg(feature = "network")]
println!("网络特性已启用");
// 平台特定代码
#[cfg(target_os = "linux")]
println!("运行在Linux系统上");
#[cfg(target_os = "windows")]
println!("运行在Windows系统上");
#[cfg(target_os = "macos")]
println!("运行在macOS系统上");
}
2.2.4 创建多二进制项目
让我们创建一个包含多个二进制目标的复杂项目:
src/bin/helper1.rs:
rust
//! 辅助工具1 - 数学计算器
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() != 4 {
eprintln!("用法: {} <操作> <数字1> <数字2>", args[0]);
eprintln!("操作: add, sub, mul, div");
std::process::exit(1);
}
let operation = &args[1];
let num1: f64 = args[2].parse().expect("无效的数字");
let num2: f64 = args[3].parse().expect("无效的数字");
let result = match operation.as_str() {
"add" => num1 + num2,
"sub" => num1 - num2,
"mul" => num1 * num2,
"div" => {
if num2 == 0.0 {
eprintln!("错误: 除数不能为零");
std::process::exit(1);
}
num1 / num2
}
_ => {
eprintln!("错误: 未知操作 '{}'", operation);
std::process::exit(1);
}
};
println!("结果: {} {} {} = {}", num1, operation, num2, result);
}
src/bin/helper2.rs:
rust
//! 辅助工具2 - 文件信息查看器
use std::env;
use std::fs;
use std::path::Path;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
eprintln!("用法: {} <文件路径>", args[0]);
std::process::exit(1);
}
let path = Path::new(&args[1]);
if !path.exists() {
eprintln!("错误: 文件不存在 '{}'", path.display());
std::process::exit(1);
}
let metadata = fs::metadata(path)?;
println!("文件信息:");
println!(" 路径: {}", path.display());
println!(" 大小: {} 字节", metadata.len());
println!(" 是否文件: {}", metadata.is_file());
println!(" 是否目录: {}", metadata.is_dir());
if let Ok(modified) = metadata.modified() {
println!(" 修改时间: {:?}", modified);
}
if let Ok(permissions) = metadata.permissions() {
println!(" 权限: {:?}", permissions);
}
Ok(())
}
2.2.5 构建脚本和自定义构建
build.rs - 自定义构建脚本:
rust
use std::env;
use std::fs;
use std::path::Path;
use std::process::Command;
fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=src/");
// 设置环境变量
let package_name = env::var("CARGO_PKG_NAME").unwrap();
let package_version = env::var("CARGO_PKG_VERSION").unwrap();
println!("cargo:warning=构建 {} 版本 {}", package_name, package_version);
// 生成版本信息文件
let out_dir = env::var("OUT_DIR").unwrap();
let version_file = Path::new(&out_dir).join("version_info.rs");
let version_info = format!(
r#"
pub const PACKAGE_NAME: &str = "{}";
pub const PACKAGE_VERSION: &str = "{}";
pub const BUILD_TIME: &str = "{}";
"#,
package_name,
package_version,
chrono::Utc::now().to_rfc3339()
);
fs::write(&version_file, version_info).unwrap();
println!("cargo:rustc-env=VERSION_INFO_RS={}", version_file.display());
// 条件编译设置
if cfg!(target_os = "linux") {
println!("cargo:rustc-cfg=unix");
}
// 链接系统库示例
if cfg!(target_os = "linux") {
println!("cargo:rustc-link-lib=dylib=dl");
}
}
2.3 代码组织结构
2.3.1 模块系统深度解析
Rust的模块系统是其代码组织的核心。让我们创建一个复杂的模块结构:
src/main.rs:
rust
// 声明外部模块
mod utils;
mod math_operations;
mod network;
// 使用use关键字导入
use utils::file_utils;
use math_operations::{basic_math, advanced_math};
use network::http_client;
// 重导出
pub use utils::Config;
fn main() {
println!("=== 模块系统演示 ===");
// 使用模块中的功能
file_utils::read_file_simulation("config.txt");
let sum = basic_math::add(10, 20);
println!("10 + 20 = {}", sum);
let factorial = advanced_math::factorial(5);
println!("5! = {}", factorial);
http_client::make_request_simulation("https://api.example.com/data");
// 使用重导出的类型
let config = Config::new("app.conf");
config.display();
}
src/utils/mod.rs:
rust
//! 工具模块
//!
//! 这个模块包含各种实用工具函数和类型。
// 子模块
pub mod file_utils;
pub mod string_utils;
// 公开的结构体
pub struct Config {
pub filename: String,
pub debug_mode: bool,
}
impl Config {
pub fn new(filename: &str) -> Self {
Self {
filename: filename.to_string(),
debug_mode: cfg!(debug_assertions),
}
}
pub fn display(&self) {
println!("配置文件: {}", self.filename);
println!("调试模式: {}", self.debug_mode);
}
}
// 模块级别的文档测试
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_config_creation() {
let config = Config::new("test.conf");
assert_eq!(config.filename, "test.conf");
}
}
src/utils/file_utils.rs:
rust
//! 文件操作工具函数
use std::path::Path;
use std::fs;
use std::io;
/// 模拟读取文件内容
///
/// # 参数
///
/// * `filename` - 要读取的文件名
///
/// # 示例
///
/// ```
/// use comprehensive_hello::utils::file_utils;
/// file_utils::read_file_simulation("config.txt");
/// ```
pub fn read_file_simulation(filename: &str) -> String {
println!("读取文件: {}", filename);
// 在实际应用中,这里会有真正的文件读取逻辑
if Path::new(filename).exists() {
format!("文件 {} 的内容", filename)
} else {
String::from("文件不存在")
}
}
/// 安全的文件读取函数
pub fn read_file_safe(filename: &str) -> Result<String, io::Error> {
fs::read_to_string(filename)
}
/// 文件信息结构体
pub struct FileInfo {
pub size: u64,
pub is_readable: bool,
pub is_writable: bool,
}
impl FileInfo {
pub fn new(filename: &str) -> Self {
let metadata = fs::metadata(filename).unwrap_or_else(|_| {
panic!("无法获取文件元数据: {}", filename)
});
Self {
size: metadata.len(),
is_readable: true, // 简化实现
is_writable: true, // 简化实现
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::NamedTempFile;
#[test]
fn test_file_info() {
let temp_file = NamedTempFile::new().unwrap();
let file_info = FileInfo::new(temp_file.path().to_str().unwrap());
assert!(file_info.size >= 0);
assert!(file_info.is_readable);
}
}
src/utils/string_utils.rs:
rust
//! 字符串处理工具
/// 反转字符串
pub fn reverse_string(s: &str) -> String {
s.chars().rev().collect()
}
/// 检查字符串是否为回文
pub fn is_palindrome(s: &str) -> bool {
let cleaned: String = s.chars()
.filter(|c| c.is_alphanumeric())
.collect::<String>()
.to_lowercase();
cleaned == reverse_string(&cleaned)
}
/// 统计单词数量
pub fn count_words(text: &str) -> usize {
text.split_whitespace().count()
}
/// 字符串转换 trait
pub trait StringConversion {
fn to_camel_case(&self) -> String;
fn to_snake_case(&self) -> String;
}
impl StringConversion for str {
fn to_camel_case(&self) -> String {
let mut result = String::new();
let mut capitalize_next = false;
for c in self.chars() {
if c == '_' {
capitalize_next = true;
} else if capitalize_next {
result.push(c.to_ascii_uppercase());
capitalize_next = false;
} else {
result.push(c);
}
}
result
}
fn to_snake_case(&self) -> String {
let mut result = String::new();
for (i, c) in self.chars().enumerate() {
if c.is_ascii_uppercase() && i > 0 {
result.push('_');
}
result.push(c.to_ascii_lowercase());
}
result
}
}
src/math_operations/mod.rs:
rust
//! 数学运算模块
pub mod basic_math;
pub mod advanced_math;
// 重导出常用功能
pub use basic_math::{add, subtract, multiply, divide};
pub use advanced_math::{factorial, fibonacci, is_prime};
src/math_operations/basic_math.rs:
rust
//! 基础数学运算
/// 加法运算
///
/// # 示例
///
/// ```
/// use comprehensive_hello::math_operations::basic_math::add;
/// assert_eq!(add(2, 3), 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
/// 减法运算
pub fn subtract(a: i32, b: i32) -> i32 {
a - b
}
/// 乘法运算
pub fn multiply(a: i32, b: i32) -> i32 {
a * b
}
/// 除法运算
///
/// # 错误
///
/// 如果除数为零,会panic
pub fn divide(a: i32, b: i32) -> i32 {
if b == 0 {
panic!("除数不能为零");
}
a / b
}
/// 安全的除法运算
pub fn divide_safe(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
Err("除数不能为零".to_string())
} else {
Ok(a / b)
}
}
src/math_operations/advanced_math.rs:
rust
//! 高级数学运算
/// 计算阶乘
///
/// # 参数
///
/// * `n` - 要计算阶乘的非负整数
///
/// # 返回值
///
/// n的阶乘,如果n=0则返回1
pub fn factorial(n: u64) -> u64 {
match n {
0 | 1 => 1,
_ => n * factorial(n - 1),
}
}
/// 计算斐波那契数列的第n项
pub fn fibonacci(n: u32) -> u64 {
if n == 0 {
return 0;
}
if n == 1 {
return 1;
}
let mut a = 0;
let mut b = 1;
for _ in 2..=n {
let temp = a + b;
a = b;
b = temp;
}
b
}
/// 检查数字是否为质数
pub fn is_prime(n: u64) -> bool {
if n <= 1 {
return false;
}
if n <= 3 {
return true;
}
if n % 2 == 0 || n % 3 == 0 {
return false;
}
let mut i = 5;
while i * i <= n {
if n % i == 0 || n % (i + 2) == 0 {
return false;
}
i += 6;
}
true
}
/// 最大公约数
pub fn gcd(mut a: u64, mut b: u64) -> u64 {
while b != 0 {
let temp = b;
b = a % b;
a = temp;
}
a
}
/// 最小公倍数
pub fn lcm(a: u64, b: u64) -> u64 {
if a == 0 || b == 0 {
0
} else {
(a * b) / gcd(a, b)
}
}
src/network/mod.rs:
rust
//! 网络相关功能
pub mod http_client;
pub mod tcp_server;
// 网络错误类型
#[derive(Debug)]
pub enum NetworkError {
ConnectionFailed,
Timeout,
InvalidResponse,
IoError(std::io::Error),
}
impl From<std::io::Error> for NetworkError {
fn from(error: std::io::Error) -> Self {
NetworkError::IoError(error)
}
}
src/network/http_client.rs:
rust
//! HTTP客户端模拟
use super::NetworkError;
/// HTTP请求方法
#[derive(Debug, Clone)]
pub enum HttpMethod {
GET,
POST,
PUT,
DELETE,
}
/// HTTP请求结构体
pub struct HttpRequest {
pub method: HttpMethod,
pub url: String,
pub headers: Vec<(String, String)>,
pub body: Option<String>,
}
impl HttpRequest {
pub fn new(method: HttpMethod, url: &str) -> Self {
Self {
method,
url: url.to_string(),
headers: Vec::new(),
body: None,
}
}
pub fn add_header(mut self, key: &str, value: &str) -> Self {
self.headers.push((key.to_string(), value.to_string()));
self
}
pub fn set_body(mut self, body: &str) -> Self {
self.body = Some(body.to_string());
self
}
}
/// 模拟HTTP请求
pub fn make_request_simulation(url: &str) -> Result<String, NetworkError> {
println!("模拟HTTP请求到: {}", url);
// 在实际应用中,这里会有真正的HTTP请求逻辑
if url.starts_with("https://") {
Ok(format!("响应来自 {}", url))
} else {
Err(NetworkError::ConnectionFailed)
}
}
/// 异步HTTP请求(需要启用async特性)
#[cfg(feature = "network")]
pub async fn make_async_request(url: &str) -> Result<String, NetworkError> {
// 在实际应用中,这里会使用真正的异步HTTP客户端
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
make_request_simulation(url)
}
2.3.2 可见性和访问控制
理解Rust的可见性规则:
rust
// src/visibility_demo.rs
mod visibility_demo {
// 公开的结构体,但字段默认私有
pub struct PublicStruct {
public_field: String, // 私有字段
pub public_field2: String, // 公开字段
}
impl PublicStruct {
// 公开的构造函数
pub fn new(value: &str) -> Self {
Self {
public_field: value.to_string(),
public_field2: value.to_string(),
}
}
// 公开的方法可以访问私有字段
pub fn get_private_field(&self) -> &str {
&self.public_field
}
// 私有方法
fn private_method(&self) {
println!("这是私有方法");
}
}
// 私有结构体,只在模块内可见
struct PrivateStruct {
field: i32,
}
// 模块内的公共接口
pub fn public_function() {
println!("这是公开函数");
private_function(); // 可以调用私有函数
}
// 私有函数,只在模块内可见
fn private_function() {
println!("这是私有函数");
}
// 嵌套模块的可见性
pub mod nested {
pub fn function() {
println!("嵌套模块的公开函数");
super::private_function(); // 可以访问父模块的私有项
}
// 只在父模块内可见
pub(crate) fn crate_visible() {
println!("只在crate内可见");
}
// 只在特定路径可见
pub(in crate::visibility_demo) fn module_visible() {
println!("只在visibility_demo模块内可见");
}
}
}
fn test_visibility() {
use visibility_demo::PublicStruct;
let instance = PublicStruct::new("test");
println!("{}", instance.public_field2); // OK
// println!("{}", instance.public_field); // 错误:字段私有
println!("{}", instance.get_private_field()); // OK
visibility_demo::public_function(); // OK
// visibility_demo::private_function(); // 错误:函数私有
visibility_demo::nested::function(); // OK
}
2.4 基础调试技巧
2.4.1 打印调试技术
Rust提供了多种打印调试的方法:
rust
// src/debugging.rs
#[derive(Debug)] // 自动实现Debug trait
struct User {
name: String,
age: u32,
email: String,
}
fn print_debugging_techniques() {
println!("=== 打印调试技术 ===");
let user = User {
name: "张三".to_string(),
age: 25,
email: "zhangsan@example.com".to_string(),
};
// 1. 基础println!
println!("用户: {}", user.name);
// 2. 调试打印
println!("用户详情: {:?}", user);
println!("美化调试: {:#?}", user);
// 3. dbg!宏 - 非常强大的调试工具
let x = 5;
let y = 10;
let sum = dbg!(x * y + 15);
dbg!(&user);
// 4. 格式化的调试输出
println!("调试信息: name={}, age={}, email={}",
user.name, user.age, user.email);
// 5. 使用eprintln!打印到标准错误
eprintln!("警告: 这是错误输出");
// 6. 条件调试打印
if cfg!(debug_assertions) {
println!("这是调试构建的额外信息");
}
}
fn advanced_dbg_usage() {
println!("\n=== 高级dbg!用法 ===");
// dbg!在表达式中的使用
let numbers = vec![1, 2, 3, 4, 5];
let result: Vec<i32> = numbers
.iter()
.map(|x| dbg!(x * 2))
.filter(|x| dbg!(x > &4))
.collect();
dbg!(result);
// 函数调用调试
fn factorial(n: u32) -> u32 {
if n <= 1 {
dbg!(1)
} else {
dbg!(n * factorial(n - 1))
}
}
dbg!(factorial(4));
}
2.4.2 断言和调试断言
rust
fn assertion_techniques() {
println!("=== 断言技术 ===");
let value = 42;
// 基础断言
assert!(value > 0);
assert_eq!(value, 42);
assert_ne!(value, 0);
// 带消息的断言
assert!(value < 100, "值应该小于100,但得到 {}", value);
// 调试断言(只在调试构建中检查)
debug_assert!(value > 0, "调试断言失败");
// 不可达代码断言
let status = "success";
match status {
"success" => println!("操作成功"),
"error" => println!("操作失败"),
_ => unreachable!("未知状态"),
}
// 实现自定义断言函数
fn assert_valid_age(age: u32) {
assert!(age <= 150, "无效的年龄: {}", age);
assert!(age > 0, "年龄必须为正数");
}
assert_valid_age(25);
// assert_valid_age(200); // 这会panic
}
fn panic_handling() {
println!("\n=== Panic处理 ===");
// 1. 基本的panic
// panic!("这是一个panic!");
// 2. 条件panic
let should_panic = false;
if should_panic {
panic!("条件触发的panic");
}
// 3. 未实现的功能
fn not_implemented() -> ! {
unimplemented!("这个功能还没有实现");
}
// 4. 未支持的功能
fn unsupported_operation() -> ! {
unreachable!("这个操作不应该被调用");
}
// 5. 可选值的解包
let maybe_value: Option<i32> = Some(42);
let value = maybe_value.expect("值不应该为None");
println!("解包的值: {}", value);
// 6. 结果的解包
let result: Result<i32, &str> = Ok(100);
let value = result.expect("操作不应该失败");
println!("结果值: {}", value);
}
2.4.3 日志系统集成
让我们集成一个完整的日志系统:
Cargo.toml添加依赖:
toml
[dependencies]
log = "0.4"
env_logger = "0.10"
[features]
default = ["logging"]
logging = ["dep:log", "dep:env_logger"]
src/logging_demo.rs:
rust
#[cfg(feature = "logging")]
use log::{debug, info, warn, error, trace};
#[cfg(feature = "logging")]
pub fn setup_logging() {
use env_logger::Env;
env_logger::Builder::from_env(Env::default().default_filter_or("info"))
.format_timestamp_millis()
.format_module_path(false)
.init();
info!("日志系统初始化完成");
}
#[cfg(feature = "logging")]
pub fn demonstrate_logging() {
trace!("这是最详细的跟踪信息");
debug!("调试信息 - 变量值: {}", 42);
info!("普通信息 - 应用程序正常执行");
warn!("警告信息 - 需要注意的情况");
error!("错误信息 - 严重问题发生");
// 结构化日志
info!(
user_id = 12345,
action = "login",
"用户执行操作"
);
}
#[cfg(not(feature = "logging"))]
pub fn setup_logging() {
println!("日志特性未启用");
}
#[cfg(not(feature = "logging"))]
pub fn demonstrate_logging() {
println!("日志特性未启用,使用println代替");
println!("[INFO] 模拟日志信息");
}
2.4.4 调试器集成
配置VS Code进行高级调试:
.vscode/launch.json:
json
{
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug Main",
"program": "${workspaceFolder}/target/debug/comprehensive_hello",
"args": [],
"cwd": "${workspaceFolder}",
"preLaunchTask": "cargo build"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug Tests",
"program": "${workspaceFolder}/target/debug/comprehensive_hello",
"args": ["--test-threads=1"],
"cwd": "${workspaceFolder}",
"preLaunchTask": "cargo test --no-run"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug Helper Tool",
"program": "${workspaceFolder}/target/debug/helper_tool",
"args": ["add", "10", "20"],
"cwd": "${workspaceFolder}",
"preLaunchTask": "cargo build --bin helper_tool"
}
]
}
.vscode/tasks.json:
json
{
"version": "2.0.0",
"tasks": [
{
"label": "cargo build",
"type": "shell",
"command": "cargo",
"args": ["build"],
"group": "build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": [
"$rustc"
]
},
{
"label": "cargo test",
"type": "shell",
"command": "cargo",
"args": ["test", "--no-run"],
"group": "build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": [
"$rustc"
]
}
]
}
2.4.5 性能调试和分析
rust
fn performance_debugging() {
println!("=== 性能调试 ===");
use std::time::Instant;
// 测量执行时间
let start = Instant::now();
// 模拟一些工作
let mut sum = 0;
for i in 0..1_000_000 {
sum += i;
}
let duration = start.elapsed();
println!("计算耗时: {:?}", duration);
println!("结果: {}", sum);
// 内存使用分析
memory_usage_analysis();
}
fn memory_usage_analysis() {
println!("\n=== 内存使用分析 ===");
use std::mem;
// 检查类型大小
println!("i32大小: {} 字节", mem::size_of::<i32>());
println!("String大小: {} 字节", mem::size_of::<String>());
println!("Vec<i32>大小: {} 字节", mem::size_of::<Vec<i32>>());
// 堆分配分析
let small_vec: Vec<i32> = vec![1, 2, 3];
let large_vec: Vec<i32> = (0..1000).collect();
println!("小向量容量: {}, 长度: {}", small_vec.capacity(), small_vec.len());
println!("大向量容量: {}, 长度: {}", large_vec.capacity(), large_vec.len());
// 内存对齐
println!("i32对齐: {} 字节", mem::align_of::<i32>());
println!("String对齐: {} 字节", mem::align_of::<String>());
}
// 基准测试示例
#[cfg(test)]
mod benchmarks {
use super::*;
#[test]
fn test_performance() {
let start = Instant::now();
// 测试代码
let result = advanced_math::fibonacci(30);
let duration = start.elapsed();
assert!(duration.as_millis() < 100, "性能测试失败: 执行时间过长");
assert_eq!(result, 832040);
}
}
2.4.6 错误处理和调试
rust
fn comprehensive_error_handling() {
println!("=== 综合错误处理 ===");
// 1. 基本的Result处理
match divide_with_result(10, 0) {
Ok(result) => println!("除法结果: {}", result),
Err(e) => println!("错误: {}", e),
}
// 2. 使用unwrap和expect
let value = divide_with_result(10, 2).unwrap();
println!("安全除法结果: {}", value);
// 3. 使用?操作符传播错误
if let Err(e) = process_division() {
println!("处理过程中出错: {}", e);
}
// 4. 自定义错误类型
match complex_operation() {
Ok(result) => println!("复杂操作成功: {}", result),
Err(MyError::DivisionError(msg)) => println!("除法错误: {}", msg),
Err(MyError::ValidationError(msg)) => println!("验证错误: {}", msg),
Err(MyError::NetworkError(msg)) => println!("网络错误: {}", msg),
}
}
fn divide_with_result(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
Err("除数不能为零".to_string())
} else {
Ok(a / b)
}
}
fn process_division() -> Result<(), String> {
let result1 = divide_with_result(20, 4)?;
let result2 = divide_with_result(result1, 2)?;
println!("链式除法结果: {}", result2);
Ok(())
}
// 自定义错误类型
#[derive(Debug)]
enum MyError {
DivisionError(String),
ValidationError(String),
NetworkError(String),
}
fn complex_operation() -> Result<i32, MyError> {
// 模拟可能失败的操作
let input = 10;
if input < 0 {
return Err(MyError::ValidationError("输入不能为负".to_string()));
}
let result = divide_with_result(input, 2)
.map_err(|e| MyError::DivisionError(e))?;
// 模拟网络操作
if result > 100 {
return Err(MyError::NetworkError("结果太大".to_string()));
}
Ok(result)
}
通过本章的全面学习,你已经深入掌握了创建、组织、构建和调试Rust程序的所有基础知识。从简单的Hello World程序到复杂的多模块项目,你现在应该能够自信地开始编写自己的Rust程序了。在下一章中,我们将深入探讨Rust的变量和数据类型系统。