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

本文详细介绍了Rust编程语言中的切片(slice)概念,包括如何从向量中创建切片、切片的借用规则以及切片在字符串(str)处理中的应用。通过示例代码展示了切片的创建、范围操作、借用规则以及错误处理方法,强调了生命周期和类型安全的重要性。同时,探讨了字符串切片的特性以及在文件扩展名提取中的实际应用。
摘要由CSDN通过智能技术生成

Rust里有切片(slice),切片是对多个连续元素的引用。

你可以借用一个vector的切片,例如:

fn main() {

let v = vec![1, 2, 3, 4, 5];

let v2 = &v[2..4];

println!("v2 = {:?}", v2);

}

// output:

// v2 = [3, 4]

复制代码

上面不是魔法。索引操作符(foo[index])被Index和IndexMut两个traits重载。

..语法只是range字面量。Ranges是定义在标准库的一些结构体。

它们可以是开放-闭合的,如果想要包含最右边的元素,可以使用=来处理:

fn main() {

// 0 or greater

println!("{:?}", (0..).contains(&100)); // true

// strictly less than 20

println!("{:?}", (..20).contains(&20)); // false

// 20 or less than 20

println!("{:?}", (..=20).contains(&20)); // true

// only 3, 4, 5

println!("{:?}", (3..6).contains(&4)); // true

}

复制代码

借用规则也适用于切片(slice):

fn tail(s: &[u8]) -> &[u8] {

&s[1..]

}

fn main() {

let x = &[1, 2, 3, 4, 5];

let y = tail(x);

println!("y = {:?}", y);

}

复制代码

上面的代码和下面是一样的:

fn tail(s: &'a [u8]) -> &'a [u8] {

&s[1..]

}

复制代码

这样子写也是合法的:

fn main() {

let y = {

let x = &[1, 2, 3, 4, 5];

tail(x)

};

println!("y = {:?}", y);

}

复制代码

但是上面的代码合法只是因为[1,2,3,4,5]是一个'static'数组。所以下面的代码是不合法的:

fn main() {

let y = {

let v = vec![1, 2, 3, 4, 5];

tail(&v)

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

};

println!("y = {:?}", y);

}

复制代码

因为一个vector是分配在堆上的,它的生命周期是不是'static'。

&str类型的值是真正的切片。

fn file_ext(name: &str) -> Option {

// this does not create a new string - it returns

// a slice of the argument.

name.split(".").last()

}

fn main() {

let name = "Read me. Or don't.txt";

if let Some(ext) = file_ext(name) {

println!("file extension: {}", ext);

} else {

println!("no file extension");

}

}

复制代码

所以借用规则也适用于这里:

fn main() {

let ext = {

let name = String::from("Read me. Or don't.txt");

file_ext(&name).unwrap_or("")

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

};

println!("extension: {:?}", ext);

}

复制代码

调用失败,函数典型情况下会返回一个Result:

fn main() {

let s = std::str::from_utf8(&[240, 159, 141, 137]);

println!("{:?}", s);

// prints: Ok("🍉")

let s = std::str::from_utf8(&[195, 40]);

println!("{:?}", s);

// prints: Err(Utf8Error { valid_up_to: 0, error_len: Some(1) })

}

复制代码

如果你想在失败的时候直接panic,你可以使用unwrap():

fn main() {

let s = std::str::from_utf8(&[240, 159, 141, 137]).unwrap();

println!("{:?}", s);

// prints: "🍉"

let s = std::str::from_utf8(&[195, 40]).unwrap();

// prints: thread 'main' panicked at 'called `Result::unwrap()`

// on an `Err` value: Utf8Error { valid_up_to: 0, error_len: Some(1) }',

// src/libcore/result.rs:1165:5

}

复制代码

或者,如果想要输出自定义信息的话可以使用.expect():

fn main() {

let s = std::str::from_utf8(&[195, 40]).expect("valid utf-8");

// prints: thread 'main' panicked at 'valid utf-8: Utf8Error

// { valid_up_to: 0, error_len: Some(1) }', src/libcore/result.rs:1165:5

}

复制代码

或者你可以使用match:

fn main() {

match std::str::from_utf8(&[240, 159, 141, 137]) {

Ok(s) => println!("{}", s),

Err(e) => panic!(e),

}

// prints 🍉

}

复制代码

或者你可以使用if let:

fn main() {

if let Ok(s) = std::str::from_utf8(&[240, 159, 141, 137]) {

println!("{}", s);

}

// prints 🍉

}

复制代码

或者你可以把错误抛到上一层:

fn main() -> Result {

match std::str::from_utf8(&[240, 159, 141, 137]) {

Ok(s) => println!("{}", s),

Err(e) => return Err(e),

}

Ok(())

}

复制代码

或者你可以使用一种更简洁的操作?:

fn main() -> Result {

let s = std::str::from_utf8(&[240, 159, 141, 137])?;

println!("{}", s);

Ok(())

}

复制代码

*操作符可以用于解引用,但是在访问内部字段或者调用方法的时候可以不进行解引用操作:

struct Point {

x: f64,

y: f64,

}

fn main() {

let p = Point { x: 1.0, y: 3.0 };

let p_ref = &p;

println!("({}, {})", p_ref.x, p_ref.y);

}

// prints `(1, 3)`

复制代码

并且解引用操作只能在实现了Copytrait的类型上使用:

struct Point {

x: f64,

y: f64,

}

fn negate(p: Point) -> Point {

Point {

x: -p.x,

y: -p.y,

}

}

fn main() {

let p = Point { x: 1.0, y: 3.0 };

let p_ref = &p;

negate(*p_ref);

// error: cannot move out of `*p_ref` which is behind a shared reference

}

复制代码// now `Point` is `Copy`

#[derive(Clone, Copy)]

struct Point {

x: f64,

y: f64,

}

fn negate(p: Point) -> Point {

Point {

x: -p.x,

y: -p.y,

}

}

fn main() {

let p = Point { x: 1.0, y: 3.0 };

let p_ref = &p;

negate(*p_ref); // ...and now this works

}

复制代码

原文链接

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值