学习rust_day07

错误处理

在Rust中没有“异常”

错误分为可恢复和不可恢复


不可恢复的错误:panic!()

两种导致panic的方式:

  • 代码中的某些行为导致panic
  • 显式的调用panic!()宏

默认情况下:
panic后,会打印失败信息,展开Stack,清理Stack

Panic后的响应

  • 展开Stack并清理数据
  • 立即终止(abort)

设置立即终止,需要在Cargo.toml中加入:

1
2
[profile.release]
panic = "abort"

使用Result处理可恢复错误

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use std::{fs::File, io::ErrorKind};

fn main() {
let file_fp = File::open("hello.txt");
//成功:返回Ok<T>, T: std::fs::File
//失败:返回Err<E>, E: std::io::Error

let file_fp = match File::open("hello.txt") {
Ok(file) => file,
Err(error) => match error.kind() {
ErrorKind::NotFound => match File::create("hello.txt") {
Ok(fc) => fc,
Err(_) => panic!("Can't create file")
},
_ => panic!("Error")
}
};

//出现错误时常用的快捷panic方式
let file_fp = File::open("hello1.txt").unwrap();
let file_fp = File::open("hello2.txt").expect("Can't open");

}use std::{fs::File, io::ErrorKind};

fn main() {
let file_fp = File::open("hello.txt");
//成功:返回Ok<T>, T: std::fs::File
//失败:返回Err<E>, E: std::io::Error

let file_fp = match File::open("hello.txt") {
Ok(file) => file,
Err(error) => match error.kind() {
ErrorKind::NotFound => match File::create("hello.txt") {
Ok(fc) => fc,
Err(_) => panic!("Can't create file")
},
_ => panic!("Error")
}
};

//出现错误时常用的快捷panic方式
let file_fp = File::open("hello1.txt").unwrap();
let file_fp = File::open("hello2.txt").expect("Can't open");

}

传播错误

将错误返回,由调用该函数的代码来决定如何处理错误.

? 运算符(operator)

使用? 运算符时

  • 如果操作成功,它会解包Ok并继续执行下一行代码
  • 如果操作失败,它会立即返回Err,并将错误传播给调用者

使用? 运算符可以避免大量的match或if let语句,使代码更简洁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use std::fs::File;
use std::io;
use std::io::{Error, Read};
use std::num::ParseIntError;

//自定义错误类型
#[derive(Debug)]
pub enum MyError {
Io(Error),
ParseInt(ParseIntError),
Other(String)
}

impl From<Error> for MyError {
fn from(value: Error) -> Self {
MyError::Io(value)
}
}

impl From<ParseIntError> for MyError {
fn from(value: ParseIntError) -> Self {
MyError::ParseInt(value)
}
}

fn read_username_from_file_test() -> Result<String, MyError> {
let mut username = String::new();
File::open("hello.txt")?.read_to_string(&mut username)?;
let num :i32= "55".parse()?;
Ok(username)
}

//默认错误类型
fn read_username_from_file() -> Result<String, io::Error> {
let mut username = String::new();
File::open("hello.txt")?.read_to_string(&mut username)?;
Ok(username)

//or
//fs::read_to_string("hello.txt")
}

fn main() {

}

泛型

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
use std::char::UNICODE_VERSION;

//在struct中使用泛型
struct Point<T, U> {
x: T,
y: U
}

fn fun() {
let integer = Point { x: 5, y: 10 };
let float = Point { x: 1.0, y: 1 };
}

//在方法中使用泛型
impl<T, U> Point<T, U> {
fn x(&self) -> &T {
&self.x
}
}

fn main() {
let number_list = vec![43, 56, 666, 1145, 33];
let result = largest(&number_list);
println!("{result}");

let char_list = vec!['c', 'f', 'w', 'a', 'k'];
let result = largest(&char_list);
println!("{result}");
}

//在函数中使用泛型
fn largest<T: PartialOrd>(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}

Trait

定义Trait

类型的行为:可以在该类型上调用的方法

Trait定义:将不同的方法签名组成一个方法签名,由此定义一套共享的行为。

Trait的实现规则

只要trait或类型其中之一属于当前crate,就可以实现该trait

合法示例:

  • 在本地类型Tweet上实现标准库的Display(trait)
  • 在标准库的Vec上实现本地的Summary(trait)

非法示例:

  • 不能在Vec上实现Display(trait)(因为两者都来自标准库)

致性和孤儿规则:
孤儿规则要求trait或类型必须属于当前crate,防止冲突实现

例:

lib.rs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
pub struct NewsArticle {
pub headline: String,
pub location: String,
pub author: String,
pub content: String
}

pub struct Tweet {
pub username: String,
pub content: String,
pub reply: bool,
pub retweet: bool
}

//定义Trait
pub trait Summary {
fn summarize(&self) -> String {
format!("(Read more from {}...)", self.summarize_author()) //Trait的默认实现
}

fn summarize_author(&self) -> String;
}

//实现Trait
impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!("{}, by {} ({})", self.headline, self.author, self.location)
}

fn summarize_author(&self) -> String {
format!("@{}", self.author)
}
}

impl Summary for Tweet {
fn summarize(&self) -> String {
format!("{}: {}", self.username, self.content)
}

fn summarize_author(&self) -> String {
format!("@{}", self.username)
}
}

//Trait Bound
pub fn notify<T: Summary>(item: &T) {
println!("{}", item.summarize());
}
//多个泛型约束 pub fn notify<T: Summary + Display>(item: &T) {}
//使用where
//fn some_fun<T, U>(t: &T, u:&U) -> i32
//where
// T: Display + Clone,
// U: Clone + Debug,
//{}

//blanket实现:可以为实现了某个trait的类型有条件地实现另一个trait
//impl<T: Display> ToString for T {}

main.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
use planb::{Summary, Tweet};

fn main() {
let tweet = Tweet {
username: String::from("A"),
content: String::from("BBBB"),
reply: false,
retweet: false
};

println!("{}", tweet.summarize());

}

学习rust_day07
https://zlsf-zl.github.io/2026/03/16/学习rust-day07/
作者
ZLSF
发布于
2026年3月16日
许可协议