马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
theme: github
highlight: an-old-hope
观看B站软件工艺师杨旭的rust教程学习纪录,有删减有增补
错误处置惩罚
- 可规复错误:如文件未找到可再次实验
- 不可规复错误:如访问索引越界
- panic!宏
- 打印错误信息
- 睁开(unwind)清算调用栈(stack),或设置制止(abort)
- 想让二进制文件更小,可以把睁开改为制止
- 在Cargo.toml中的[profile.release]设置panic='abort'
睁开清算调用栈会沿着栈往回走并清算每个碰到的数据
中断不举行清算直接制止步伐,内存由os清算
不可规复的错误
panic
- fn main(){
- let v = vec![1,2,3];
- println!("{}",v[5]);//越界,
- }
复制代码 设置RUST_BACKTRACE=1表现回溯信息,错误代码以上是我们调用的代码,错误代码以下是调用main.rs的代码
- #win
- set RUST_BACKTRACE=1 && cargo run
- #linux&macos
- RUST_BACKTRACE=1 && cargo run
复制代码 可规复的错误
Result在prelude中,不须要显式导入
- enum Result<T, E> {
- Ok(T),
- Err(E),
- }
复制代码
- T 代表乐成时返回的 Ok 成员中的数据的范例
- E 代表失败时返回的 Err 成员中的错误的范例
match处置惩罚错误
- use std::fs::File;
- fn main() {
- let f = File::open("hello.txt");
- let f = match f {
- Ok(file) => file,
- Err(error) => {
- panic!("打开文件发生错误:{:?}", error)
- }
- };
- }
复制代码 match匹配差异的错误
打开文件时,文件存在则返回文件内容,文件不存在则创建文件并返回文件,创建失败制止步伐
- use std::{fs::File, io::ErrorKind};
- fn main() {
- let f = File::open("hello.txt");
- let f = match f {
- Ok(file) => file, //返回文件内容
- Err(error) => match error.kind() {
- ErrorKind::NotFound => match File::create("hello.txt") {
- Ok(fc) => fc,
- Err(e) => panic!("创建文件出错!{:?}", e),
- },
- other_error => panic!("打开文件出错!{:?}", other_error),
- },
- };
- }
复制代码 闭包改良
- use std::{fs::File, io::ErrorKind};
- fn main() {
- let _f = File::open("hello.txt").unwrap_or_else(|error| {//调用闭包
- if error.kind() == ErrorKind::NotFound {
- File::create("hello.txt").unwrap_or_else(|error| {
- panic!("创建错误!{:?}", error);
- })
- } else {
- panic!("打开错误!{:?}", error);
- }
- });
- }
复制代码 unwrap
Ok则返回Ok里的内容,Err则调用panic!宏
- use std::fs::File;
- fn main() {
- let f = File::open("hello.txt");
- let f = match f {
- Ok(file) => file,
- Err(error) => {
- panic!("打开文件出错!{:?}", error);
- }
- };
- //等价于
- let f = File::open("hello.txt").unwrap();
- }
复制代码 expect
Ok则返回Ok里的内容,Err则调用panic!宏,可以指定错误信息
- use std::fs::File;
- fn main() {
- let f = File::open("hello.txt").expect("打开文件出错!");
- }
复制代码 流传错误
将错误返回给调用者
- use std::fs::File;
- use std::io::{self, Read};
- fn main() {
- let result = read_username_from_file();//错误信息传播到调用者
- println!("{:?}", &result);
- }
- fn read_username_from_file() -> Result<String, io::Error> {
- let f = File::open("hello.txt");
- let mut f = match f {
- Ok(file) => file, //成功打开文件返回文件并继续
- Err(e) => return Err(e), //打开失败返回错误信息
- };
- let mut s = String::new();
- match f.read_to_string(&mut s) {
- //读取文件内容
- Ok(_) => Ok(s), //读取成功返回信息
- Err(e) => Err(e), //读取失败返回错误
- } //返回结果
- }
复制代码 ?流传错误,与上面的代码功能类似,
- use std::fs::File;
- use std::io::{self, Read};
- fn main() {
- let result = read_username_from_file(); //错误信息传播到调用者
- println!("{:?}", &result);
- }
- fn read_username_from_file() -> Result<String, io::Error> {
- let mut f = File::open("hello.txt")?;
- let mut s = String::new();
- f.read_to_string(&mut s)?;//Result为Ok,Ok()中的值就是表达式的结果,Result为Err,Err就是整个函数的返回值
- Ok(s)
- }
复制代码 链式调用
- use std::fs::File;
- use std::io::{self, Read};
- fn main() {
- let result = read_username_from_file(); //错误信息传播到调用者
- println!("{:?}", &result);
- }
- fn read_username_from_file() -> Result<String, io::Error> {
- let mut s = String::new();
- File::open("hello.txt")?.read_to_string(&mut s)?;
- Ok(s)
- }
复制代码 生命周期
克制悬垂引用(danging reference),x的生命周期比r短
- fn main() {
- let r;
- {
- let x = 5;
- r = &x;//x离开作用域,drop x
- }
- println!("r:{}", r);//借用了一个不存在的变量
- }
复制代码
- Rust每个引用都有自己的生命周期
- 生命周期是引用保持有效的作用域
- 大多数情况:生命周期是隐式的、可被推断的
- 当引用的生命周期大概以差异的方式相互关联时,须要手动标注生命周期
- 现实生命周期是标注中生命周期较小的一个
- //告诉借用检查器函数参数(x、y)、返回值(str)的生命周期和函数的生命周期一样
- //实际生命周期是标注中生命周期较小的x
- fn find_smallest<'a>(x: &'a str, y: &'a str) -> &'a str {
- if x < y {
- x
- } else {
- y
- }
- }
- fn main() {
- let x = "apple";
- let y = "banana";
- let result = find_smallest(x, y);
- println!("最短的字符串: {}", result);
- }
复制代码 指定生命周期参数的精确方式依赖函数实现的具体功能
- //返回值的生命周期只与x有关,y可以不标注
- fn find_smallest<'a>(x: &'a str, y: &str) -> &'a str {
- x//返回x
- }
- fn main() {
- let x = "apple";
- let y = "banana";
- let result = find_smallest(x, y);
- println!("最短的字符串: {}", result);
- }
复制代码 从函数返回引用时,返回范例的生命周期参数要与此中一个参数的生命周期匹配
- fn find_smallest<'a>(x: &'a str, y: &str) -> &'a str {
- let s1 = String::from("hello world");
- //返回s1的切片,也就是对s1的引用,离开函数后s1被drop,该函数返回了一个指向未知数据的引用
- s1.as_str()
- } //drop s1
- fn main() {
- let x = "apple";
- let y = "banana";
- let result = find_smallest(x, y);
- println!("最短的字符串: {}", result);
- }
复制代码
- 生命周期在函数方法的参数中:输入生命周期
- 生命周期在函数方法的返回值中:输出生命周期
生命周期省略规则:
- 每个引用范例的参数都有自己的生命周期
- 假如只有1个输入生命周期,那么该生命周期被赋给全部的输出生命周期
- 假如有多个输入生命周期,但此中一个参数是&self或&mut self(仅方法),那么self的生命周期会被赋给全部的输出生命周期
- struct Foo<'a> {//可以不标注,在impl里标注
- data: &'a i32, //每个引用类型的参数都有自己的生命周期,可以不标注
- }
- struct Foo2 {}
- impl<'a> Foo<'a> {
- //如果只有1个输入生命周期,那么该生命周期被赋给所有的输出生命周期
- fn new(data: &'a i32) -> Foo<'a> {//这个生命周期会被推断出来,可以不标注
- Foo { data }
- }
- //如果只有1个输入生命周期,那么该生命周期被赋给所有的输出生命周期
- fn get_data(&self) -> &'a i32 {//这个生命周期会被推断出来,可以不标注
- self.data
- }
- //如果有多个生命周期,但其中一个参数是`&self`或`&mut self`(仅方法),那么`self`的生命周期会被赋给所有的输出生命周期
- fn modify_data(&mut self, new_data: &'a i32) -> i32 {//可以推断返回值生命周期,但impl生命周期为'a,确保引用有效性,需要标注生命周期
- self.data = new_data;
- 12 //这个返回值没有意义
- }
- //如果有多个生命周期,但其中一个参数是`&self`或`&mut self`(仅方法),那么`self`的生命周期会被赋给所有的输出生命周期
- fn combine_data1<'b>(&'a self, other: &'a i32) -> &i32 {//可以推断返回值的生命周期,但是要确保引用有效性,需要对参数和函数标注生命周期
- if *self.data > *other {
- self.data
- } else {
- other
- }
- }
- }
- impl Foo2 {
- //不满足推断规则需要对参数返回值标注生命周期
- fn combine_data2<'q>(a: &'q i32, b: &'q i32) -> &'q i32 {
- if a < b {
- a
- } else {
- b
- }
- }
- }
- fn main() {
- let x = 5;
- let y = 10;
- let mut foo = Foo::new(&x);
- println!("初始化的值: {}", foo.get_data()); //初始化的值: 5
- foo.modify_data(&y);
- println!("修改后的值: {}", foo.get_data()); //修改后的值: 10
- let combined_data1 = foo.combine_data1(&y);
- println!("返回最大的: {}", combined_data1); //返回最大的: 10
- let combine_data2 = Foo2::combine_data2(&x, &y);
- println!("返回最小的:{}", combine_data2); //返回最小的:5
- }
复制代码 struct字段生命周期
- 在struct背面标注
- 在impl后标注
- 这些生命周期是struct范例的一部分
impl块里的生命周期
静态生命周期
'static:整个步伐的连续时间
- fn main() {
- let s1: &'static str = "hello world";
- //等价于
- let s2: &str = "hello owrld";
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金 |