rust美服为什么给我半了_【翻译】半小时快速了解Rust(二)

一些方法也会造成panic。例如,Option类型可以包含某些东西或者什么也不包含。如果在它上面执行unwrap()操作,当它什么也不包含的时候,就会panic(译者注:这里panic感觉保留原词比较好,翻译成恐慌感觉怪怪的,打架了理解意思就好)。

fn main() {

let o1: Option = Some(128);

o1.unwrap(); // this is fine

let o2: Option = None;

o2.unwrap(); // this panics!

}

// output: thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:378:21

复制代码

Option 不是一个结构体,它是一个带有两个变量的enum

enum Option {

None,

Some(T),

}

impl Option {

fn unwrap(self) -> T {

// enums variants can be used in patterns:

match self {

Self::Some(t) => t,

Self::None => panic!(".unwrap() called on a None option"),

}

}

}

use self::Option::{None, Some};

fn main() {

let o1: Option = Some(128);

o1.unwrap(); // this is fine

let o2: Option = None;

o2.unwrap(); // this panics!

}

// output: thread 'main' panicked at '.unwrap() called on a None option', src/main.rs:11:27

复制代码

Result也是一个枚举(enum),它可以包含某物或者是一个错误:

enum Result {

Ok(T),

Err(E),

}

复制代码

如果包含的是一个错误,那么它在进行unwrap操作的时候也会panic。

变量绑定有一个"生命周期(lifetime)":

fn main() {

// `x` doesn't exist yet

{

let x = 42; // `x` starts existing

println!("x = {}", x);

// `x` stops existing

}

// `x` no longer exists

}复制代码

类似地,引用也有一个生命周期:

fn main() {

// `x` doesn't exist yet

{

let x = 42; // `x` starts existing

let x_ref = &x; // `x_ref` starts existing - it borrows `x`

println!("x_ref = {}", x_ref);

// `x_ref` stops existing

// `x` stops existing

}

// `x` no longer exists

}复制代码

引用的生命周期不能超过它所借用(引用)的变量绑定的声明周期:

fn main() {

let x_ref = {

let x = 42;

&x

};

println!("x_ref = {}", x_ref);

// error: `x` does not live long enough

}

复制代码

一个变量绑定可以进行多次不可变借用:

fn main() {

let x = 42;

let x_ref1 = &x;

let x_ref2 = &x;

let x_ref3 = &x;

println!("{} {} {}", x_ref1, x_ref2, x_ref3);

}

复制代码

当变量绑定被借用的时候,是不能被修改的:

fn main() {

let mut x = 42;

let x_ref = &x;

x = 13;

println!("x_ref = {}", x_ref);

// error: cannot assign to `x` because it is borrowed

}

复制代码

当一个变量(绑定)被不可变借用(引用)的时候,就不能再被可变借用(引用):

fn main() {

let mut x = 42;

let x_ref1 = &x;

let x_ref2 = &mut x;

// error: cannot borrow `x` as mutable because it is also borrowed as immutable

println!("x_ref1 = {}", x_ref1);

}

复制代码

函数参数里的引用也有生命周期:

fn print(x: &i32) {

// `x` is borrowed (from the outside) for the

// entire time this function is called.

}

复制代码

带有引用参数的函数可以被拥有不同生命周期的借用(借用)来调用,所以:

所有带有引用参数的函数都是泛型的

生命周期是泛型参数

生命周期的命名以'开头:

// elided (non-named) lifetimes:

fn print(x: &i32) {}

// named lifetimes:

fn print(x: &'a i32) {}

复制代码

这就允许函数返回引用,返回的引用的生命周期依赖于参数的生命周期:

struct Number {

value: i32,

}

fn number_value(num: &'a Number) -> &'a i32 {

&num.value

}

fn main() {

let n = Number { value: 47 };

let v = number_value(&n);

// `v` borrows `n` (immutably), thus: `v` cannot outlive `n`.

// While `v` exists, `n` cannot be mutably borrowed, mutated, moved, etc.

}复制代码

当只有单个输入生命周期的时候,可以不进行命名(译者注:就就是可以省略不写),函数里所有的一切都有相同的生命周期,所以下面的两个函数是等价的:

fn number_value(num: &'a Number) -> &'a i32 {

&num.value

}

fn number_value(num: &Number) -> &i32 {

&num.value

}复制代码

结构体关于生命周期也可以是泛型的,这使得结构体里可以含有引用:

struct NumRef {

x: &'a i32,

}

fn main() {

let x: i32 = 99;

let x_ref = NumRef { x: &x };

// `x_ref` cannot outlive `x`, etc.

}

复制代码

下面是相同的代码,但是带有一个额外的函数:

struct NumRef {

x: &'a i32,

}

fn as_num_ref(x: &'a i32) -> NumRef {

NumRef { x: &x }

}

fn main() {

let x: i32 = 99;

let x_ref = as_num_ref(&x);

// `x_ref` cannot outlive `x`, etc.

}复制代码

下面也是相同的代码,但是带有"省略(elided)"的生命周期:

struct NumRef {

x: &'a i32,

}

fn as_num_ref(x: &i32) -> NumRef {

NumRef { x: &x }

}

fn main() {

let x: i32 = 99;

let x_ref = as_num_ref(&x);

// `x_ref` cannot outlive `x`, etc.

}复制代码

impl块在生命周期方面也是泛型的:

impl NumRef {

fn as_i32_ref(&'a self) -> &'a i32 {

self.x

}

}

fn main() {

let x: i32 = 99;

let x_num_ref = NumRef { x: &x };

let x_i32_ref = x_num_ref.as_i32_ref();

// neither ref cannot outlive `x`

}

复制代码

但是你也可以在这里进行省略:

impl NumRef {

fn as_i32_ref(&self) -> &i32 {

self.x

}

}

复制代码

如果你都不需要生命周期的命名,还可以省略得更多一些:

impl NumRef {

fn as_i32_ref(&self) -> &i32 {

self.x

}

}复制代码

有一个特殊的生命周期叫'static',它的意思是在整个程序的运行期间都是有效的。

字符串字面量(String literals)就是'static':

struct Person {

name: &'static str,

}

fn main() {

let p = Person {

name: "fasterthanlime",

};

}复制代码

但是有所有权的字符串不是静态(全局变量)的:

struct Person {

name: &'static str,

}

fn main() {

let name = format!("fasterthan{}", "lime");

let p = Person { name: &name };

// error: `name` does not live long enough

}复制代码

在上面的例子里,局部的name不是一个'static str',它是一个String。它是被动态分配然后将会被释放。它的生命周期要比整个程序的生命周期短(尽管它在main函数里)。

为了在Person里存储一个非-'static'的字符串,可以采取下面两种方式:

A)写成关于生命周期的泛型:

struct Person {

name: &'a str,

}

fn main() {

let name = format!("fasterthan{}", "lime");

let p = Person { name: &name };

// `p` cannot outlive `name`

}

复制代码

或者

B)拥有字符串的所有权:

struct Person {

name: String,

}

fn main() {

let name = format!("fasterthan{}", "lime");

let p = Person { name: name };

// `name` was moved into `p`, their lifetimes are no longer tied.

}

复制代码

顺便提一下:在一个结构体字面量里,当一个字段被赋值为一个具有相同名字的变量绑定时:

let p = Person { name: name };

复制代码

它可以被简写成下面这样:

let p = Person { name };

复制代码

对于Rust中的许多类型,都有被拥有(owned)的和不被拥有(non-owned)的变量:

字符串(Strings): String是被拥有(owned)的,&str是一个引用(reference)。

路径(Paths):PathBuf是被拥有(owned)的, &Path是一个引用(reference);

集合(Collections): Vec是被拥有(owned)的,&[T]是一个引用(reference)。

欢迎关注我的微信公众号:

ad7e3800ffd65b76a962487d4c90255e.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值