熟悉 Rust 语法

Rust 是一种很棒的语言,它结合了系统编程的强大功能和现代语言特性,可用于 Web 开发和区块链。

然而,在学习 Rust 时,一个阻碍是熟悉它的语法。

在本文中,我会尽力提供一些示例,让你对这些语法感到舒适。

入门:变量和类型

让我们从基础开始:变量。

默认情况下,Rust 变量是不可变的。如果你习惯了像 Python 或 JavaScript 这样的允许变量改变的语言,这可能听起来很奇怪。

fn main() {
    let x = 5; // x 默认是不可变的
    // x = 6; // 取消注释会导致编译错误
​
    let mut y = 5; // y 是可变的
    y = 6; // 这里没有问题
}

注意 let 关键字吗?这是你在 Rust 中声明变量的方式。如果你想改变一个变量,可以用 mut 关键字使其可变。

类型注释

Rust 拥有出色的类型推断:编译器通常知道你的变量类型。

但有时,你需要自己指定类型:

// 这里,我们明确地表示 z 是一个 32 位整数
let z: i32 = 10; 

Rust 的类型系统是它的一个巨大优势,所以尽早熟悉它是值得的。

函数

如果你使用过其他语言,Rust 中的函数看起来会很熟悉。但有一些语法上的怪癖需要注意。

fn add(a: i32, b: i32) -> i32 {
    a + b // 没有分号表示这是返回值
}

注意我们使用 -> 来定义函数的返回类型。另外,这里没有 return 关键字;如果你省略分号,Rust 默认返回最后一个表达式。

一旦习惯了,这还是不错的。

所有权和借用

好了,这里事情变得有趣了。Rust 的所有权模型让它与众不同,但一开始可能会有些棘手。

让我们看另一个例子。

所有权

在 Rust 中,每个值都有一个变量作为它的所有者。

当所有者超出作用域时,值就被丢弃。这是 Rust 避免内存泄漏的方式。

fn main() {
    let s1 = String::from("hello");
    let s2 = s1; // String 的所有权被移动到 s2,s1 现在无效
​
    // println!("{}", s1); // 这会导致编译时错误
}

在这里,s1 在被移动到 s2 之后不再拥有 String 的所有权。

如果你在那之后尝试使用 s1,Rust 不会让你这样做。

借用

但如果你想使用一个值而不获取它的所有权呢?

这就是借用的用武之地。你可以通过使用引用来借用一个值:

fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1); // 我们在这里借用了 s1
​
    println!("The length of '{}' is {}.", s1, len);
}
​
fn calculate_length(s: &String) -> usize {
    s.len()
}

在这个例子中,&s1 是 s1 的 引用。calculate_length 函数临时借用了 s1 而不获取所有权。函数完成后,s1 仍然有效。这非常酷。

生命周期

生命周期是 Rust 用来追踪引用有效时间的方式。

一开始可能会有些混乱,但它们对于安全内存管理至关重要。

让我们看看一个非常基本的例子,来熟悉一下。

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

这里,'a 是一个生命周期参数。这意味着引用 x 和 y 的生命周期至少要和返回值一样长。这确保我们不会返回一个已经被丢弃的引用。

模式匹配

Rust 的 match 语句就像一个强大的 switch。它是我最喜欢的语言部分之一,因为它非常强大和表达力丰富。

fn main() {
    let number = 7;
​
    match number {
        1 => println!("One!"),
        2 => println!("Two!"),
        3 | 4 | 5 => println!("Three, Four, or Five!"),
        6..=10 => println!("Between Six and Ten!"),
        _ => println!("Anything else!"),
    }
}

match 语句将一个值与多个模式进行比较,并运行第一个匹配模式的代码。_ 是一个捕获所有模式,当你想处理任何未明确匹配的情况时非常有用。

用模式匹配进行解构

你还可以用 match 来解构复杂的数据类型,比如元组或枚举。

fn main() {
    let pair = (2, 5);
​
    match pair {
        (0, y) => println!("First is zero and y is {}", y),
        (x, 0) => println!("x is {} and second is zero", x),
        _ => println!("No zeroes here!"),
    }
}

这只是冰山一角。

match 可以做更多的事情,但这应该给你一个坚实的基础。

错误处理

Rust 没有异常。相反,它使用 ResultOption 类型来处理错误。最初可能感觉有点冗长,但它比未检查的异常更安全。

fn main() {
    let result = divide(10, 2);
    match result {
        Ok(v) => println!("Result is {}", v),
        Err(e) => println!("Error: {}", e),
    }
}
​
fn divide(a: i32, b: i32) -> Result<i32, String> {
    if b == 0 {
        Err(String::from("Division by zero"))
    } else {
        Ok(a / b)
    }
}

这里,Result 是一个可以是 Ok(成功)或 Err(错误)的类型。这强制你处理成功和失败的情况,这对于编写健壮的代码非常有用。

? 操作符

为了使错误处理更方便,Rust 提供了 ? 操作符。它是传播错误的简写。

fn main() -> Result<(), String> {
    let result = divide(10, 0)?; // 如果 divide 返回 Err,它会立即从函数返回
    println!("Result is {}", result);
    Ok(())
}

这是 Rust 的说法,“如果有错误,就返回它。”

高级语法:Traits、泛型等

现在我们已经掌握了基础知识,让我们深入探讨更高级的主题。

Traits:接口(有点像)

Traits 有点像其他语言中的接口。它们定义了不同类型可以实现的共享行为。

trait Summary {
    fn summarize(&self) -> String;
}
​
struct Article {
    title: String,
    content: String,
}
​
impl Summary for Article {
    fn summarize(&self) -> String {
        format!("{}: {}", self.title, self.content)
    }
}

在这里,我们定义并实现了 Article 结构体的 Summary trait。现在,任何 Article 都可以被总结。Traits 对于编写通用和可重用的代码非常强大。

泛型:编写灵活的代码

泛型让你可以编写适用于任何数据类型的函数和类型。

fn largest<T: PartialOrd>(list: &[T]) -> &T {
    let mut largest = &list[0];
    for item in list {
        if item > largest {
            largest = item;
        }
    }
    largest
}

这个函数适用于任何可以比较的类型 T。PartialOrd 部分是 trait 约束,这意味着 T 必须实现 PartialOrd trait,允许进行顺序比较。

实用技巧:编写惯用的 Rust

  • 使用 rustfmt:Rust 有一个内置的格式化工具,可以保持你的代码整洁。只需在你的项目目录中运行 cargo fmt

  • 使用 Rust Analyzer:这个强大的 IDE 扩展提供代码补全、重构等功能。它就像一个精通 Rust 的助手。

  • Clippy:这是一个 Rust 的 linter,捕捉常见错误并提供改进建议。运行 cargo clippy 看看它发现了什么。

结论

这篇简短的文章是为了让你对 Rust 更加熟悉。

我有一系列关于这些具体主题的免费视频。

你可以在这里查看。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幻想多巴胺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值