
Rust 常用函数/方法/语法速查手册
用途:写代码时随手查,不用每次都去翻官方文档。按"我要干什么"分类,不是按语言特性分类,方便直接定位。
目录
- 字符串处理(String / &str)
- 数字与类型转换
- Vec 常用方法
- HashMap 常用方法
- Option 常用方法
- Result 常用方法
- 迭代器常用方法
- 输入输出(io)
- 常用语法糖 / 技巧
- 格式化打印速查(
{}里能写什么) - 常见类型速查表
- 网络编程常用(std::net)
- 常见报错对照表
1. 字符串处理(String / &str)
先搞清楚 String 和 &str 的关系:String 是"拥有所有权、可增长"的字符串(存在堆上);&str 是"借用的字符串切片"(只读,不拥有数据)。字符串字面量 "abc" 的类型就是 &str。函数参数优先写 &str(更通用,String 能自动转成 &str 传进去)。
| 方法 | 签名(简化) | 作用 | 示例 |
|---|---|---|---|
.len() | &self -> usize | 字节长度(不是字符数!中文占3字节) | "abc".len() → 3 |
.trim() | &self -> &str | 去掉首尾空白(含换行符) | " 8080\n".trim() → "8080" |
.is_empty() | &self -> bool | 是否为空字符串 | "".is_empty() → true |
.contains(pat) | &self, &str/char -> bool | 是否包含子串/字符 | "a.b".contains('.') → true |
.starts_with(pat) | &self, &str -> bool | 是否以...开头 | "https://x".starts_with("https") → true |
.ends_with(pat) | &self, &str -> bool | 是否以...结尾 | "file.txt".ends_with(".txt") → true |
.split(pat) | &self, &str/char -> Iterator | 按分隔符切分,返回迭代器 | "1-100".split('-') → ["1","100"] |
.splitn(n, pat) | 同上+限制份数 | 最多切成n份 | "a:b:c".splitn(2,':') → ["a","b:c"] |
.replace(from, to) | &self, &str, &str -> String | 替换所有匹配 | "a-b".replace("-","_") → "a_b" |
.to_string() | &self -> String | &str转String | "abc".to_string() |
.to_owned() | &self -> String | 效果同to_string() | "abc".to_owned() |
String::from(s) | &str -> String | 效果同to_string(),更常见写法 | String::from("abc") |
.as_str() | &self -> &str | String转&str(借用) | s.as_str() |
.push_str(s) | &mut self, &str | 在末尾追加字符串 | s.push_str("world") |
.push(c) | &mut self, char | 在末尾追加单个字符 | s.push('!') |
.insert_str(i, s) | &mut self, usize, &str | 在指定位置插入字符串 | s.insert_str(0, "https://") |
.to_uppercase() | &self -> String | 转大写 | "abc".to_uppercase() → "ABC" |
.to_lowercase() | &self -> String | 转小写 | "ABC".to_lowercase() → "abc" |
.parse::<T>() | &self -> Result<T, E> | 解析成数字等类型 | "8080".parse::<u16>() |
.chars() | &self -> Iterator<char> | 按字符遍历(处理中文安全) | for c in s.chars() {} |
.bytes() | &self -> Iterator<u8> | 按字节遍历 | for b in s.bytes() {} |
.trim_start_matches(pat) | &self, &str -> &str | 去掉开头的匹配内容 | url.trim_start_matches("https://") |
format!(...) | 宏,同println!语法 | 拼字符串(不打印,返回String) | format!("{}:{}", ip, port) |
记忆技巧:凡是"看一眼、判断"的方法(len/is_empty/contains/starts_with),签名都是 &self;凡是"改内容"的(push_str/insert_str),签名都是 &mut self;凡是"生成新字符串"的(replace/to_uppercase),都返回一个全新的 String,不改原字符串。
2. 数字与类型转换
| 操作 | 写法 | 说明 |
|---|---|---|
| 字符串转数字 | s.parse::<u32>() | 返回 Result<u32, ParseIntError>,可能失败 |
| 数字转字符串 | n.to_string() | 几乎所有数字类型都有这个方法 |
| 数字转数字(安全,可能失败) | u16::try_from(300_i32) | 返回 Result,超范围会是 Err |
| 数字转数字(不检查,会截断) | n as u16 | ⚠️ 超范围会静默截断出错误值,谨慎使用 |
| 判断奇偶 | n % 2 == 0 | 没有专门的is_even方法 |
| 取绝对值 | n.abs() | 仅有符号类型(i32等)有 |
| 最大/最小值 | a.max(b) / a.min(b) | 两数比较 |
| 类型的最大/最小值 | u16::MAX / u16::MIN | 常量,u16::MAX是65535 |
| 四舍五入(浮点数) | f.round() | 还有 .floor()向下、.ceil()向上 |
记忆技巧:as 转换是"暴力转换",超出目标类型范围会出乱码般的错误结果(不会报错,是"静默"出错,最容易埋雷);try_from 是"安全转换",超范围直接给你 Err,写校验逻辑(比如端口号范围检查)优先用 try_from 或手动比较范围。
3. Vec 常用方法
| 方法 | 签名(简化) | 作用 | 示例 | ||
|---|---|---|---|---|---|
Vec::new() | -> Vec<T> | 创建空Vec | let v: Vec<u32> = Vec::new(); | ||
vec![...] | 宏 | 创建并初始化Vec | vec![1, 2, 3] | ||
.push(x) | &mut self, T | 尾部添加元素 | v.push(80) | ||
.pop() | &mut self -> Option<T> | 移除并返回最后一个元素 | v.pop() → Some(80)或None | ||
.len() | &self -> usize | 元素个数 | v.len() | ||
.is_empty() | &self -> bool | 是否为空 | v.is_empty() | ||
.get(i) | &self, usize -> Option<&T> | 安全获取(越界返回None,不panic) | v.get(0) | ||
v[i] | 索引访问 | 直接取值(越界会panic!) | v[0] | ||
.contains(&x) | &self, &T -> bool | 是否包含某元素 | v.contains(&80) | ||
.sort() | &mut self | 原地排序(从小到大) | v.sort() | ||
.sort_by_key(f) | &mut self, closure | 按指定规则排序 | `v.sort_by_key(\ | x\ | x.port)` |
.reverse() | &mut self | 原地反转顺序 | v.reverse() | ||
.iter() | &self -> Iterator<&T> | 借用迭代(不拿走所有权) | for x in v.iter() {} | ||
.into_iter() | self -> Iterator<T> | 拿走所有权的迭代 | for x in v.into_iter() {} | ||
.first() / .last() | &self -> Option<&T> | 第一个/最后一个元素 | v.first() | ||
.clear() | &mut self | 清空所有元素 | v.clear() | ||
.remove(i) | &mut self, usize -> T | 移除指定下标元素(会移动后面所有元素,O(n)) | v.remove(0) | ||
.retain(f) | &mut self, closure | 保留满足条件的元素,原地过滤 | `v.retain(\ | x\ | *x > 100)` |
.extend(iter) | &mut self, IntoIterator | 把另一个集合的元素全部加进来 | v.extend(vec![4,5]) | ||
.concat() | 用于 Vec<Vec<T>> | 把多个Vec拼成一个 | [[1,2],[3,4]].concat() → [1,2,3,4] |
记忆技巧:v[i] 越界直接崩程序(panic),v.get(i) 越界给你 None——处理不确定来源的下标(比如用户输入的索引)一定用 .get(),不要直接用 []。
4. HashMap 常用方法
use std::collections::HashMap;| 方法 | 签名(简化) | 作用 | 示例 |
|---|---|---|---|
HashMap::new() | -> HashMap<K,V> | 创建空map | let mut m: HashMap<u16,bool> = HashMap::new(); |
.insert(k, v) | &mut self, K, V -> Option<V> | 插入(如果key已存在,返回旧值) | m.insert(80, true) |
.get(&k) | &self, &K -> Option<&V> | 查找,找不到返回None | m.get(&80) |
.get_mut(&k) | &mut self, &K -> Option<&mut V> | 查找并拿到可变引用(可以直接改) | if let Some(v) = m.get_mut(&80) { *v = false; } |
.contains_key(&k) | &self, &K -> bool | 是否存在某key | m.contains_key(&80) |
.remove(&k) | &mut self, &K -> Option<V> | 删除并返回值 | m.remove(&80) |
.entry(k).or_insert(v) | 链式调用 | key不存在就插入默认值,存在就返回现有值的可变引用 | *m.entry(80).or_insert(0) += 1; |
.keys() | &self -> Iterator<&K> | 遍历所有key | for k in m.keys() {} |
.values() | &self -> Iterator<&V> | 遍历所有value | for v in m.values() {} |
.iter() | &self -> Iterator<(&K,&V)> | 遍历所有键值对 | for (k,v) in m.iter() {} |
.len() | &self -> usize | 键值对数量 | m.len() |
记忆技巧:entry().or_insert() 是统计计数的标准套路("没有就建、有就累加"),几乎每个用HashMap做统计的场景都会用到,务必记熟。遍历顺序不保证,需要有序输出要额外 .sort() 或换 BTreeMap。
5. Option 常用方法
| 方法 | 作用 | 示例 | ||
|---|---|---|---|---|
.is_some() | 是否有值 | opt.is_some() | ||
.is_none() | 是否为空 | opt.is_none() | ||
.unwrap() | 取值,None时panic(慎用) | opt.unwrap() | ||
.unwrap_or(default) | 取值,None时用默认值 | opt.unwrap_or(0) | ||
.unwrap_or_else(f) | 取值,None时调用闭包生成默认值 | `opt.unwrap_or_else(\ | \ | compute())` |
.unwrap_or_default() | 取值,None时用类型的默认值(0/空串等) | opt.unwrap_or_default() | ||
.map(f) | 有值就转换,None还是None | `opt.map(\ | x\ | x * 2)` |
.and_then(f) | 有值就调用f(f本身返回Option),常用于链式操作 | `opt.and_then(\ | x\ | if x>0 {Some(x)} else {None})` |
.ok_or(err) | 转成Result,None变成Err(err) | opt.ok_or("没找到") | ||
if let Some(x) = opt { ... } | 只关心有值的情况 | 常用写法,比match简洁 |
记忆技巧:.map() 是"有值就加工一下,还是Option";.and_then() 是"有值就调用一个'本身也返回Option'的函数,避免出现Option<Option
6. Result 常用方法
| 方法 | 作用 | 示例 | ||
|---|---|---|---|---|
.is_ok() | 是否成功 | res.is_ok() | ||
.is_err() | 是否失败 | res.is_err() | ||
.unwrap() | 取值,Err时panic(慎用,只适合原型阶段) | res.unwrap() | ||
.unwrap_or(default) | 取值,Err时用默认值 | res.unwrap_or(0) | ||
.ok() | 转成Option,Err变成None(丢弃错误信息) | res.ok() | ||
.map(f) | 成功值加工一下 | `res.map(\ | x\ | x * 2)` |
.map_err(f) | 转换错误类型/错误信息 | `res.map_err(\ | e\ | format!("失败:{}",e))` |
? | 失败直接把Err向上抛,成功取出值继续 | let x = risky_fn()?; | ||
.expect(msg) | 类似unwrap,panic时带自定义提示信息 | res.expect("连接必须成功") |
记忆技巧:正式代码里,尽量不用 unwrap(),改用 match、?、或者 .unwrap_or(默认值);只有在写原型/测试代码,图快的时候才用 unwrap()。expect(msg) 比 unwrap() 稍好一点,至少panic时能看到你写的提示信息,方便定位问题。
7. 迭代器常用方法
先转成迭代器:.iter()(借用)/ .into_iter()(拿走所有权)/ .iter_mut()(可变借用)
| 方法 | 作用 | 示例 | ||
|---|---|---|---|---|
.filter(f) | 保留满足条件的元素 | `v.iter().filter(\ | x\ | **x > 100)` |
.map(f) | 把每个元素转换成别的 | `v.iter().map(\ | x\ | x * 2)` |
.collect() | 把迭代器收集成具体集合(Vec/HashMap等),常需要类型标注 | let v: Vec<u16> = iter.collect(); | ||
.count() | 统计满足条件的数量 | v.iter().filter(...).count() | ||
.sum() | 求和 | let total: u32 = v.iter().sum(); | ||
.max() / .min() | 最大/最小值,返回Option | v.iter().max() | ||
.find(f) | 找第一个满足条件的元素,返回Option | `v.iter().find(\ | x\ | **x == 80)` |
.any(f) | 是否存在满足条件的元素,返回bool | `v.iter().any(\ | x\ | *x > 1000)` |
.all(f) | 是否所有元素都满足条件 | `v.iter().all(\ | x\ | *x > 0)` |
.enumerate() | 附带下标一起遍历 | for (i, x) in v.iter().enumerate() {} | ||
.zip(other) | 两个迭代器一一配对 | a.iter().zip(b.iter()) | ||
.take(n) | 只取前n个 | v.iter().take(5) | ||
.skip(n) | 跳过前n个 | v.iter().skip(5) | ||
.rev() | 反转顺序 | v.iter().rev() | ||
.chain(other) | 把两个迭代器接在一起 | a.iter().chain(b.iter()) | ||
.for_each(f) | 对每个元素执行操作(不返回新集合) | `v.iter().for_each(\ | x\ | println!("{}", x))` |
.partition(f) | 一次遍历,按条件分成两个集合 | `let (a, b): (Vec<_>,Vec<_>) = v.iter().partition(\ | x\ | **x>100);` |
记忆技巧:迭代器方法都是"链式调用",可以一直 . 下去(v.iter().filter(...).map(...).collect()),中间过程都是"懒执行"(不会立刻算),只有调用了 .collect()/.count()/.sum() 这类"消费型"方法才会真正触发计算——这个特性叫"惰性求值",性能上比每一步都生成中间Vec要好。
8. 输入输出(io)
use std::io;| 操作 | 写法 | 说明 |
|---|---|---|
| 读一行输入 | io::stdin().read_line(&mut s) | s必须是&mut String,返回Result<usize,Error>(usize是字节数) |
| 打印(带换行) | println!("{}", x) | |
| 打印(不换行) | print!("{}", x) | 有时需要手动use std::io::Write; io::stdout().flush().unwrap();才会立刻显示 |
| 打印到标准错误 | eprintln!("{}", x) | 命令行工具打印错误信息的惯例,不是标准输出 |
| 调试打印(打印结构体等) | println!("{:?}", x) | 需要类型实现Debug(大部分标准类型自动支持,自定义struct需要#[derive(Debug)]) |
| 美化调试打印 | println!("{:#?}", x) | 多行缩进格式,适合复杂结构体/嵌套数据 |
9. 常用语法糖 / 技巧
// if let:只关心Option/Result的一种情况时,比match简洁
if let Some(x) = opt {
println!("{}", x);
}
// while let:循环处理,直到不满足模式为止(比如不断从Vec里pop)
while let Some(x) = stack.pop() {
println!("{}", x);
}
// ? 运算符:错误/None向上传播(第6章重点)
let x = risky()?;
// 元组解构
let (a, b) = (1, 2);
let (min, max) = (ports.iter().min(), ports.iter().max());
// 数组/Vec的模式匹配(match)
match arr.as_slice() {
[] => println!("空"),
[x] => println!("只有一个: {}", x),
[first, .., last] => println!("首:{} 尾:{}", first, last),
}
// 用 _ 忽略不需要的值
let (_, port) = ("192.168.1.1", 8080);
for _ in 0..3 { /* 不需要循环变量时 */ }
// 链式Option/Result判断多个条件(match guard)
match port {
p if p < 1024 => println!("知名端口"),
p if p < 49152 => println!("注册端口"),
_ => println!("动态端口"),
}
// 一行式条件表达式(if是表达式,有返回值)
let status = if port == 80 { "http" } else { "other" };
// 结构体更新语法:基于已有实例创建新实例,只改部分字段
let t2 = Target { port: 443, ..t1 };
// #[derive(...)] 自动实现常用trait,不用手写
#[derive(Debug, Clone, PartialEq)]
struct Target { ip: String, port: u16 }
// Debug: 支持 {:?} 打印
// Clone: 支持 .clone()
// PartialEq: 支持 == 比较10. 格式化打印速查({} 里能写什么)
println!("{}", x); // Display格式(人类可读)
println!("{:?}", x); // Debug格式(调试用,需要类型支持)
println!("{:#?}", x); // 美化的Debug格式,多行缩进
println!("{:5}", x); // 最小宽度5,右对齐(数字默认)补空格
println!("{:<5}", x); // 左对齐,宽度5
println!("{:>5}", x); // 右对齐,宽度5
println!("{:^5}", x); // 居中,宽度5
println!("{:05}", x); // 宽度5,不足补0(常用于格式化IP/端口对齐)
println!("{:.2}", f); // 浮点数保留2位小数
println!("{:x}", n); // 十六进制小写(网络包分析常用)
println!("{:X}", n); // 十六进制大写
println!("{:08x}", n); // 十六进制,宽度8,补0(常见于格式化MAC地址/十六进制dump)
println!("{:b}", n); // 二进制
println!("{:o}", n); // 八进制
println!("{name}", name=x); // 具名参数
println!("{0} {1} {0}", a, b); // 按位置索引,可重复引用11. 常见类型速查表
| 类型 | 说明 | 常见用途 |
|---|---|---|
u8 | 0~255 | 字节数据,网络包解析常用 |
u16 | 0~65535 | 端口号(刚好匹配范围) |
u32 | 0~约42亿 | 一般计数、IPv4地址的数字形式 |
u64 | 更大范围 | 时间戳、大文件大小 |
i32 | 有符号,约-21亿~21亿 | 一般整数运算,默认整数类型 |
usize | 平台相关(64位系统通常是u64) | 集合长度、索引,len()都返回这个 |
f64 | 双精度浮点 | 默认浮点类型 |
bool | true/false | |
char | 单个Unicode字符(4字节) | |
&str | 字符串切片(借用) | 函数参数首选 |
String | 拥有所有权的字符串 | 需要修改/长期持有时用 |
Vec<T> | 动态数组 | |
[T; N] | 固定长度数组(编译期确定N) | [u8; 4]常表示IPv4地址的4个字节 |
&[T] | 数组/Vec的切片(借用) | 函数参数,比&Vec<T>更通用 |
Option<T> | 可能有值可能没有 | |
Result<T,E> | 可能成功可能失败 | |
(A,B,...) | 元组,固定个数、可以不同类型 | 简单地打包少量数据,不想专门定义struct时用 |
12. 网络编程常用(std::net)
use std::net::{TcpStream, TcpListener, SocketAddr, IpAddr, Ipv4Addr};
use std::time::Duration;
// 建立TCP连接(阻塞,一直等到成功或失败)
let stream = TcpStream::connect("127.0.0.1:8080");
// 建立TCP连接,带超时(网络工具里更常用,避免一直卡住)
let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
let stream = TcpStream::connect_timeout(&addr, Duration::from_millis(500));
// 监听端口(写服务端/简单的listener时用)
let listener = TcpListener::bind("0.0.0.0:8080").unwrap();
for stream in listener.incoming() {
// 处理每个连接
}
// 手动构造IP地址
let ip = Ipv4Addr::new(192, 168, 1, 1);
// 判断字符串是不是合法IP
let is_valid: bool = "192.168.1.1".parse::<IpAddr>().is_ok();reqwest(HTTP客户端,需要额外加依赖)常用写法:
// 同步(简单场景)
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking"] }
let resp = reqwest::blocking::get("https://example.com")?;
println!("{}", resp.status());
println!("{}", resp.text()?);
// 异步(推荐,性能更好)
// Cargo.toml: reqwest = "0.12", tokio = { version = "1", features = ["full"] }
let resp = reqwest::get("https://example.com").await?;
let body = resp.text().await?;13. 常见报错对照表
| 报错关键字 | 原因 | 怎么修 |
|---|---|---|
value borrowed after move | 变量被移动后又用 | 加.clone(),或改用引用&T |
cannot borrow ... as mutable | 同时存在可变和不可变引用 | 缩短某个引用的存活范围,让借用不重叠 |
cannot move out of ... which is behind a shared reference | 试图从&T里拿走所有权 | 用.clone()拿一份,或改成只用引用 |
mismatched types | 类型对不上 | 检查是不是String/&str没转,或数字类型不一致 |
the trait bound ... is not satisfied | 用了某个方法但类型没实现对应trait | 常见于自定义struct忘了加#[derive(Debug)]等 |
use of moved value | 用了已经被移动走的变量 | 同"value borrowed after move" |
missing lifetime specifier | 函数返回引用但编译器无法推断存活多久 | 加生命周期标注'a,或改成返回String(拿所有权,不用操心生命周期) |
unused variable (warning) | 变量声明了没用 | 不影响运行,可以在变量名前加_消除警告,如let _x = 5; |
E0502 / E0382 等错误码 | Rust错误码 | 可以直接把错误码丢进搜索引擎,官方文档对每个错误码都有详细解释和示例 |
使用建议:这份手册按"我要干什么"分类,不用背,遇到问题先想"我要做的事属于哪一类"(字符串处理?集合操作?错误处理?),来这里对应章节查表,比每次都搜索引擎慢慢翻要快。写多了自然就记住了。