
代码写得像诗一样优雅,还是像草稿纸一样凌乱?选择权在你手里!
想象一下,你去朋友家做客,发现他家厨房:
你还会想在他家吃饭吗?😰
代码也是一样!就算功能再强大,如果代码风格一塌糊涂,别人(包括三个月后的你自己)根本不想看,更别提维护了。
今天咱们就来聊聊 Rust 的代码风格规范,让你的代码从"垃圾堆"变成"样板间"!
其他语言:代码风格?随便你,开心就好~
Rust:我不允许! 😤
Rust 社区有个共识:代码是写给人看的,顺便让编译器能执行。所以 Rust 提供了一套"官方强迫症套餐":
工具 | 类比 | 作用 |
|---|---|---|
rustfmt | 家政阿姨 | 自动把代码整理得整整齐齐 |
clippy | 挑剔的代码审查员 | "这里可以优化""那里有潜在 bug" |
命名规范 | 起名字的艺术 | 让人一眼看懂这是干啥的 |
文档注释 | 产品说明书 | 告诉别人怎么用你的代码 |
错误示例(格式化前):
// 这代码看得我眼睛疼...
fn calculate_area (radius:f32)->f32{let pi=3.14159;return pi*radius*radius;}
struct Point{x:i32,y:i32}
fn main ( ) { let p=Point{x:,y:};println!("x={},y={}",p.x,p.y);}
编译器内心 OS: "我是能编译,但我真的不想..."
正确做法:
# 安装 rustfmt(通常随 Rust 一起安装)
rustup component add rustfmt
# 格式化当前项目
cargo fmt
# 检查格式是否正确(不修改)
cargo fmt --check
格式化后:
// 清爽多了!
fn calculate_area(radius: f32) -> f32 {
let pi = 3.14159;
return pi * radius * radius;
}
struct Point {
x: i32,
y: i32,
}
fn main() {
let p = Point { x: , y: };
println!("x={}, y={}", p.x, p.y);
}
💡 最佳实践: 在 IDE 里设置"保存时自动格式化",养成好习惯!
安装:
rustup component add clippy
错误示例(能编译但有警告):
fn main() {
let x = ;
let y = ;
// clippy: 这写法太啰嗦了!
if x == {
println!("x is 10");
}
// clippy: 可以用 push_str 或者 format!
let mut s = String::new();
s = s + "hello";
// clippy: 这个迭代可以简化
for i in .. {
println!("{}", i);
}
}
运行 clippy:
cargo clippy
clippy 会吐槽:
warning: 条件判断总是为真
warning: 字符串拼接可以用更高效的写法
warning: 迭代范围可以简化
优化后:
fn main() {
let x = ;
// 如果真的要检查,用 match 或者去掉这个判断
if x == {
println!("x is 10");
}
// 正确的字符串拼接
let mut s = String::new();
s.push_str("hello");
// 或者
let s = format!("hello{}", x);
// 简洁的迭代
(..).for_each(|i| println!("{}", i));
}
Rust 的命名规范就像公司的着装要求:什么场合穿什么衣服。
类型 | 命名规范 | 示例 |
|---|---|---|
变量/函数 | snake_case(小写 + 下划线) | user_name, calculate_total |
类型/结构体/枚举 | PascalCase(大写开头) | UserProfile, HttpResponse |
常量/静态变量 | SCREAMING_SNAKE_CASE(全大写) | MAX_SIZE, DEFAULT_TIMEOUT |
Trait | PascalCase | Display, Clone, Iterator |
宏 | snake_case + ! | println!, vec!, my_macro! |
错误示例:
// ❌ 不要这样写!
let UserName = "Larry"; // 变量不该用 PascalCase
fn CALCULATE_AREA() {} // 函数不该全大写
struct my_struct {} // 结构体首字母要大写
const max_size = ; // 常量应该全大写
正确示例:
// ✅ 这样写才对!
let user_name = "Larry";
fn calculate_area() {}
struct MyStruct {}
const MAX_SIZE: i32 = ;
💡 记忆口诀:
Rust 的文档注释可以直接生成漂亮的文档网站,这是真的香!
基础文档注释:
/// 计算圆的面积
///
/// # 参数
/// * `radius` - 圆的半径,必须为正数
///
/// # 返回值
/// 返回圆的面积(f32 类型)
///
/// # 示例
/// ```
/// let area = calculate_area(5.0);
/// assert!(area > 0.0);
/// ```
///
/// # 错误
/// 如果半径为负数,返回 -1.0
fn calculate_area(radius: f32) -> f32 {
if radius < 0.0 {
return -1.0;
}
std::f32::consts::PI * radius * radius
}
生成文档:
cargo doc --open
模块文档:
//! # 数学工具模块
//!
//! 这个模块提供各种数学计算函数
//!
//! ## 包含的功能
//! - 圆形计算
//! - 三角形计算
//! - 向量运算
pub mod circle;
pub mod triangle;
💡 文档注释 vs 普通注释:
/// - 文档注释(给用你代码的人看的)// - 普通注释(给维护代码的人看的,包括未来的你)问题: 有些代码格式化后反而难看了
// 格式化前(其实挺清晰)
let result = very_long_function_name(
arg1,
arg2,
arg3,
);
// 格式化后(换行太多)
let result = very_long_function_name(arg1, arg2, arg3);
解决: 用 #[rustfmt::skip] 跳过特定代码
#[rustfmt::skip]
let matrix = [
[, , ],
[, , ],
[, , ],
];
新手常见反应: "哇,clippy 给了我 100 个警告,我是不是写了一坨屎?"
别慌! clippy 的建议分等级:
解决: 先修 error,再修 warning,info 可以慢慢来。
错误示例:
/// 设置名字
/// # 参数
/// * `name` - 名字
fn set_name(name: String) {
self.name = name;
}
吐槽: "我当然知道这是设置名字的!不然叫 set_name 干嘛?"
正确做法: 写为什么和注意事项
/// 设置用户名字
///
/// # 注意事项
/// - 名字会被转换为小写存储
/// - 长度限制为 3-20 个字符
/// - 不能包含特殊字符
///
/// # 参数
/// * `name` - 用户显示的名字
fn set_name(name: String) {
// ...
}
重构前(😱 警告密集):
mod user {
pub struct User{pub name:String,pub age:i32,pub email:String}
pub fn create_user(n:String,a:i32,e:String)->User{
if a<{panic!("age can't be negative")}
User{name:n,age:a,email:e}
}
pub fn is_adult(u:&User)->bool{
if u.age>={return true}else{return false}
}
}
重构后(✨ 清爽整洁):
//! 用户模块
//!
//! 提供用户结构体和相关操作
/// 用户信息结构体
///
/// # 字段
/// * `name` - 用户名称
/// * `age` - 年龄(必须 >= 0)
/// * `email` - 邮箱地址
#[derive(Debug, Clone)]
pub struct User {
pub name: String,
pub age: i32,
pub email: String,
}
/// 创建新用户
///
/// # 参数
/// * `name` - 用户名称
/// * `age` - 年龄
/// * `email` - 邮箱
///
/// # 返回值
/// 返回新创建的 User 实例
///
/// # 示例
/// ```
/// let user = create_user("Larry".to_string(), 25, "larry@example.com".to_string());
/// assert_eq!(user.age, 25);
/// ```
pub fn create_user(name: String, age: i32, email: String) -> User {
if age < {
panic!("年龄不能为负数!你当用户是时间旅行者吗?");
}
User { name, age, email }
}
/// 检查用户是否成年
///
/// # 参数
/// * `user` - 用户引用
///
/// # 返回值
/// 如果年龄 >= 18 返回 true
pub fn is_adult(user: &User) -> bool {
user.age >=
}
重构步骤:
cargo fmt - 先格式化cargo clippy - 看建议
核心要点:
金句时间:
"代码风格不是束缚,而是让你和队友都能睡个好觉的保障。"
下篇预告: 第 48 篇咱们来聊聊 Rust 的常用库推荐 - 标准库有哪些神器?第三方库哪个最香?生态系统到底有多丰富?敬请期待!