Rust 类型转换语法大全
Rust 提供了多种类型转换机制,以下是详细的分类和语法:
1. 隐式转换 (类型强制转换, Coercions)
Rust 只在特定情况下进行隐式类型转换:
rust
// 解引用强制多态 (Deref Coercion)
let s: &str = &String::from("hello");
// 数组/切片指针转换
let arr: [i32; 3] = [1, 2, 3];
let slice: &[i32] = &arr;
// 函数项到函数指针
fn foo() {}
let f: fn() = foo;
// 生存期延长
let s: &'static str = "hello";
let s_ref: &str = s;
2. 显式转换
2.1 as 运算符(基本类型转换)
rust
// 数值类型转换
let x: i32 = 42;
let y: f64 = x as f64; // i32 -> f64
let z: u8 = x as u8; // i32 -> u8
// 指针类型转换
let ptr: *const i32 = &x as *const i32;
let mut_ptr: *mut i32 = &mut x as *mut i32;
// 引用到原始指针
let ref_x: &i32 = &x;
let raw_ptr: *const i32 = ref_x as *const i32;
// 枚举到整数
enum Color { Red = 0xff0000, Green = 0x00ff00 }
let color_val = Color::Red as u32;
// 字符到整数
let c: char = 'A';
let code: u32 = c as u32;
2.2 From 和 Into trait(安全的类型转换)
rust
use std::convert::{From, Into};
// From: 从其他类型创建自身
struct Number {
value: i32,
}
impl From<i32> for Number {
fn from(item: i32) -> Self {
Number { value: item }
}
}
let num = Number::from(30);
let num: Number = 30.into(); // Into 会自动实现
// TryFrom/TryInto(可能失败的转换)
use std::convert::{TryFrom, TryInto};
impl TryFrom<i32> for Number {
type Error = String;
fn try_from(value: i32) -> Result<Self, Self::Error> {
if value >= 0 {
Ok(Number { value })
} else {
Err("值不能为负数".to_string())
}
}
}
let result: Result<Number, _> = 5.try_into();
3. 类型推断和标注
3.1 使用 ::<> (turbofish) 语法
rust
// 泛型函数类型推断
let x = "42".parse::<i32>().unwrap();
let vec = Vec::<i32>::with_capacity(10);
// 指定迭代器类型
let nums: Vec<i32> = vec![1, 2, 3];
let squares = nums.iter().map(|x| x * x).collect::<Vec<_>>();
3.2 类型标注
rust
let x: i32 = 42; // 变量标注
let y = 42u8; // 字面量后缀
let z = 0xff_u32; // 带下划线的字面量
// 函数返回值标注
fn get_number() -> i32 { 42 }
4. 智能指针转换
4.1 Deref trait
rust
use std::ops::Deref;
struct MyBox<T>(T);
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
let my_box = MyBox(5);
let x: i32 = *my_box; // 解引用转换
4.2 Box, Rc, Arc 转换
rust
use std::rc::Rc;
use std::sync::Arc;
let boxed = Box::new(5);
let rc = Rc::new(5);
let arc = Arc::new(5);
// 类型转换
let value: i32 = *boxed;
let cloned_rc: Rc<i32> = rc.clone();
5. 字符串转换
rust
// &str 和 String 互转
let s_str: &str = "hello";
let s_string: String = s_str.to_string(); // 或 String::from(s_str)
let back_str: &str = &s_string;
// 字节数组转换
let bytes: &[u8] = s_str.as_bytes();
let str_from_bytes = std::str::from_utf8(bytes).unwrap();
// 字符迭代器
let chars: Vec<char> = s_str.chars().collect();
let from_chars: String = chars.into_iter().collect();
// 格式化转换
let formatted = format!("数字: {}", 42);
let int_from_str: i32 = "42".parse().unwrap();
6. 自定义转换 trait
6.1 AsRef 和 AsMut
rust
fn print_bytes<T: AsRef<[u8]>>(data: T) {
let bytes = data.as_ref();
// 处理字节
}
print_bytes("hello"); // &str 实现了 AsRef<[u8]>
print_bytes(vec![1, 2, 3]); // Vec<u8> 实现了 AsRef<[u8]>
// AsMut 示例
fn modify<T: AsMut<[i32]>>(mut data: T) {
let slice = data.as_mut();
slice[0] = 42;
}
6.2 Borrow 和 BorrowMut
rust
use std::borrow::Borrow;
fn check<T: Borrow<str>>(s: T) {
let borrowed: &str = s.borrow();
// 使用 borrowed
}
check("hello");
check(String::from("world"));
7. 模式匹配中的类型转换
rust
enum Message {
Text(String),
Number(i32),
}
let msg = Message::Number(42);
match msg {
Message::Text(s) => println!("文本: {}", s),
Message::Number(n) if n > 0 => println!("正数: {}", n),
Message::Number(n) => println!("数字: {}", n),
}
// if let 语法
if let Message::Number(x @ 0..=100) = msg {
println!("0-100之间的数字: {}", x);
}
8. 高级类型转换技巧
8.1 使用 transmute(不安全)
rust
use std::mem;
// 必须在 unsafe 块中使用
unsafe {
let x: i32 = 42;
let y: f32 = mem::transmute(x); // 重新解释字节
// 指针类型转换
let ptr: *const i32 = &x;
let ptr_usize: usize = mem::transmute(ptr);
}
8.2 使用 union 进行类型双关
rust
union IntOrFloat {
i: i32,
f: f32,
}
let mut u = IntOrFloat { i: 42 };
unsafe {
println!("整数: {}", u.i);
u.f = 3.14;
println!("浮点数: {}", u.f);
}
9. 关联类型和泛型约束
rust
trait Processor {
type Input;
type Output;
fn process(&self, input: Self::Input) -> Self::Output;
}
struct StringProcessor;
impl Processor for StringProcessor {
type Input = String;
type Output = usize;
fn process(&self, input: String) -> usize {
input.len()
}
}
// 使用泛型约束进行转换
fn convert<T, U>(value: T) -> U
where
T: Into<U>,
{
value.into()
}
10. 常见的转换习惯用法
rust
// Option/Result 转换
let opt: Option<i32> = Some(42);
let res: Result<i32, ()> = opt.ok_or(());
// 迭代器转换
let vec = vec![1, 2, 3];
let doubled: Vec<i32> = vec.iter().map(|x| x * 2).collect();
// 闭包类型转换
let add_one = |x: i32| -> i32 { x + 1 };
let fn_ptr: fn(i32) -> i32 = add_one;
// 切片转换
let arr = [1, 2, 3, 4, 5];
let slice: &[i32] = &arr[1..4]; // [2, 3, 4]
// 元组转换
let tuple = (1, "hello", 3.14);
let (a, b, c) = tuple; // 解构
最佳实践建议
- 优先使用安全的转换 :
From/Into>as>transmute - 利用类型推断:尽可能让编译器推断类型
- 显式优于隐式:在可能混淆的地方明确标注类型
- 处理转换失败 :使用
TryFrom/TryInto处理可能失败的转换 - 注意性能 :了解不同转换的成本(如
String到&str是零成本)
选择哪种转换方式取决于具体场景:
- 简单数值转换:
as - 自定义类型转换:实现
From/Into - 可能失败的转换:
TryFrom/TryInto - 引用类型转换:
AsRef/AsMut - 不安全的底层转换:
transmute(谨慎使用)