RUST 笔记 (五)

错误处理

不可恢复的错误

panic!宏

可恢复的错误

Result<T, E>

enum Result<T, E> {
    Ok(T),
    Err(E),
}
失败时 panic 的简写
  1. unwarp:如果 Result 值是成员 Ok,unwrap 会返回 Ok 中的值。如果 Result 是成员 Err,unwrap 会为我们调用 panic!
  2. expect:支持自定义失败时的错误信息
错误传播(类似java中的方法上抛出异常)
  1. 方法必须返回 Result<T, E>类型的值
  2. 例如读取文件总是会返回一个Result类型,需要用match 匹配结果,简单的写法如unwrap或者expect,但都是不可恢复的异常,更简单的写法是:?,且支持向上抛出异常。如果 Result 的值是 Ok,这个表达式将会返回 Ok 中的值而程序将继续执行。如果值是 Err,Err 中的值将作为整个函数的返回值

泛型

  1. 先声明再使用
  2. 实现时必须在 impl 后面声明 T
  3. Rust 通过在编译时进行泛型代码的 单态化(monomorphization)来保证效率
函数中的泛型,如:fn largest(list: &[T]) -> T {}
结构体中的泛型
struct Point<T> {
    x: T,
    y: T,
}
枚举定义中的泛型
enum Option<T> {
    Some(T),
    None,
}
enum Result<T, E> {
    Ok(T),
    Err(E),
}

方法中的枚举数据泛型
struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}


trait :定义共享的行为

  1. trait 类似于其他语言中的常被称为 接口(interfaces)的功能,虽然有一些不同;
  2. trait 定义是一种将方法签名组合起来的方法,目的是定义一个实现某些目的所必需的行为的集合。
pub trait Summarizable {
    fn summary(&self) -> String;
}

为类型实现 trait

结构体
impl Summarizable for NewsArticle {}

trait 支持默认实现

pub trait Summarizable {
    fn summary(&self) -> String {
        String::from("(Read more...)")
    }
}

对泛型的参数指定 trait bound 限制

pub fn notify<T: Summarizable>(item: T) {
    println!("Breaking news! {}", item.summary());
} //在 T 上使用 trait bounds 来指定 item 必须是实现了 Summarizable trait 的类型:

简写

fn some_function<T: Display + Clone, U: Clone + Debug>(t: T, u: U) -> i32 {}

也可简写为

fn some_function<T, U>(t: T, u: U) -> i32
    where T: Display + Clone,
          U: Clone + Debug
{}

生命周期和与引用有效性

  1. 为什么需要生命周期: Rust 中的每一个引用都有其 生命周期(lifetime),也就是引用保持有效的作用域。大部分时候生命周期是隐含并可以推断的,正如大部分时候类型也是可以推断的一样。类似于当因为有多种可能类型的时候必须注明类型,也会出现引用的生命周期以一些不同方式相关联的情况,所以 Rust 需要我们使用泛型生命周期参数来注明他们的关系,这样就能确保运行时实际使用的引用绝对是有效的。
  2. 生命周期的作用:避免了垂悬引用

例子:

fn longest(x: &str, y: &str) -> &str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}//编译不同通过,将会出现有关生命周期的错误,因为传入两个引用,返回一个引用,rust不知道要在函数结束前释放掉哪个变量

指定生命周期:通过注解
1. 生命周期注解并不改变任何引用的生命周期的长短
2. 生命周期注解所做的就是将多个引用的生命周期联系起来。

泛型类型参数生命周期注解写法:
&i32        // a reference
&'a i32     // a reference with an explicit lifetime
&'a mut i32 // a mutable reference with an explicit lifetime
函数中的生命周期注解
  1. 只存在签名中,不存在任何代码体中
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}// 编译将会通过,函数会返回一个同样也与生命周期 'a 存在的一样长的字符串 slice

结构体中的生命周期注解
struct ImportantExcerpt<'a> {
    part: &'a str,
}

生命周期省略

  1. 部分函数没有生命周期注解却能编译是由于一些历史原因,因为更多的明确的模式被合并和添加到编译器中是完全可能的。未来只会需要更少的生命周期注解。称为生命周期省略规则
  2. 函数或方法的参数的生命周期被称为 输入生命周期(input lifetimes),而返回值的生命周期被称为 输出生命周期
  3. 三条规则:
    1. 每一个是引用的参数都有它自己的生命周期参数
    2. 如果只有一个输入生命周期参数,那么它被赋予所有输出生命周期参数
    3. 如果有多个输入生命周期参数,且有&self参数,则&self的生命周期将被赋予到输出生命周期参数
方法中的生命周期注解
impl<'a> ImportantExcerpt<'a> {
    fn level(&self) -> i32 {
        3
    }
}

静态生命周期

  1. 一种 特殊的生命周期:'static。'static 生命周期存活于整个程序期间。所有的字符串字面值都拥有 'static 生命周期
let s: &'static str = "I have a static lifetime.";

一个复杂的例子:结合泛型类型参数、trait bounds 和生命周期

use std::fmt::Display;

fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a str
    where T: Display
{
    println!("Announcement! {}", ann);
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

总结

泛型类型参数意味着代码可以适用于不同的类型。trait 和 trait bounds 保证了即使类型是泛型的,这些类型也会拥有所需要的行为。由生命周期注解所指定的引用生命周期之间的关系保证了这些灵活多变的代码不会出现悬垂引用。而所有的这一切发生在编译时所以不会影响运行时效率

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值