又学一门新语言

在开始单片机开发学习之前,针对esp32上较常使用的几个开发工具和语言做了一点研究。

工具主要有乐鑫官方提供的 ESP-IDF,以及 MicroPythonArduino

  1. ESP-IDF是乐鑫官方提供的开发框架,支持C/C++,是最底层的开发方式,也是最灵活的。

  2. MicroPython是Python的一个子集,支持Python语言,是最简单的开发方式。

  3. Arduino是一个开源的硬件开发平台,支持C/C++,简单而成熟,是最流行的开发方式。

考虑到生态、性能以及拓展性。决定排除MicroPython。但是我之前一直从事软件开发,基本用的都是Java/Kotlin,Python,JavaScript等不需要考虑内存释放的高级语言,对于C/C++这种底层语言,还是上大学的时候学了一点,基本都忘记了。所以这次需要从底层语言开始重新学习。

然后找到了esp-rs,发现ESP-IDF也支持Rust,而且最近Rust很火,大概看了一下语言特性,它的语法还是比较直观简洁的。无论C/C++还是Rust都要从头学,所以决定干脆学习Rust。

有趣的特色

一些通用或比较简单的编程概念就不赘述了,可以通过查阅文档快速了解rust中的写法。不过Rust有一些很不同的语法和特性,这里简单列举一下。

强大的枚举类型 - Enum

https://kaisery.github.io/trpl-zh-cn/ch06-01-defining-an-enum.html

Rust的枚举类型是一种强大的数据类型,它可以包含多个不同的值,每个值可以是不同的类型。枚举类型可以用来表示一组相关的值,比如颜色、方向、状态等。

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

不一样的接口 - Trait

https://kaisery.github.io/trpl-zh-cn/ch10-02-traits.html

Rust的Trait类似于其他高级语言中的接口,但是更加强大。Trait是一种抽象类型,它定义了一组方法,但是没有提供方法的具体实现。Trait可以被用来定义方法的签名,然后在具体的类型上实现这些方法。

Trait可以被用来实现多态,可以在不同的类型上实现相同的Trait,然后通过Trait对象来调用这些方法。

pub trait Summary {
    fn summarize(&self) -> String;
}

pub struct NewsArticle {
    pub headline: String,
    pub location: String,
    pub author: String,
    pub content: String,
}

impl Summary for NewsArticle {
    fn summarize(&self) -> String {
        format!("{}, by {} ({})", self.headline, self.author, self.location)
    }
}

独特的内存管理 - 所有权

https://kaisery.github.io/trpl-zh-cn/ch04-01-what-is-ownership.html

Rust是一种系统编程语言,它的设计目标是提供一种安全、并发、实用的编程语言。

除了一些基本语法的不同外,Rust最大的特点就是不一样的内存控制机制。通过所有权系统,能够最大程度在编译期间检查内存安全问题,避免了一些常见的内存错误,比如空指针、野指针、内存泄漏等。

Rust的内存管理有三个基本规则:

  1. 每一个值都有一个变量,这个变量被称为这个值的所有者。
  2. 一个值的所有者在离开作用域时,这个值将被销毁。
  3. 一个值的所有者可以将这个值的所有权转移给另一个变量。
fn main() {
    let s1 = String::from("hello");

    let len = calculate_length(&s1);

    println!("The length of '{s1}' is {len}.");
}

fn calculate_length(s: &String) -> usize { // s is a reference to a String
    s.len()
} // Here, s goes out of scope. But because it does not have ownership of what
  // it refers to, nothing happens.

无需垃圾回收 - 生命周期

https://kaisery.github.io/trpl-zh-cn/ch10-03-lifetime-syntax.html

Rust没有垃圾回收,但是有生命周期。生命周期是一种编译时的检查机制,用来确保引用的有效性。生命周期是一种标记,用来指示引用的有效范围。

Rust的生命周期规则:

  1. 每一个引用都有一个生命周期。
  2. 生命周期是引用的有效范围。
  3. 引用的生命周期不能超过它所引用的值的生命周期。
  4. 生命周期的标记是一个单引号,比如’a。
  5. 生命周期的标记可以是任意的标识符,但是通常使用’a、‘b、‘c等。
  6. 生命周期的标记可以在函数签名/结构体/Trait中使用,用来指示引用的有效范围。
fn longest<'a>(x: &'a str, y: &str) -> &'a str {
    x
}

智能指针 - Box

https://kaisery.github.io/trpl-zh-cn/ch15-01-box.html

Rust的智能指针是一种特殊的指针,它包含了指向堆内存的指针,以及一些元数据,比如长度、容量等。智能指针可以用来管理堆内存,避免内存泄漏、野指针等问题。

Rust的智能指针有很多种,比如Box、Rc、Arc、RefCell等。其中Box是最简单的一种,它只包含了一个指向堆内存的指针,没有其他元数据。

let b = Box::new(5);

总结

Rust语言整体学习难度比常见高级语言要高一些,但是它的语法和特性都是非常有趣的。不推荐初学者直接从Rust开始学习,但是如果你已经有一定的编程经验而且想要尝试除C++以外的底层语言,那么Rust是一个非常好的选择。