Rust 全面指南:从基础到高级,一网打尽 Rust 的编程知识
作者:mmseoamin日期:2023-12-11

RUST入门大全

  • 前言
    • Rust介绍
    • Rust VS Java
    • Rust cargo
    • Rust变量
    • Rust数据类型
    • Rust字符串
    • Rust Vec(可变数组)
    • Rust HashTable(Map)
    • Rust逻辑判断
    • Rust 循环
    • Rust结构
    • RustTrait(接口)
    • Rust注解
    • Rust模块
    • Rust Cargo.toml
    • Rust常用库

      前言

      因为在学习Rust过程中,因为代码量不是太多,所以有一些学完就忘了,特此记录一些Rust知识点

      Rust介绍

      1. Rust是什么?

      Rust是一种现代的、强类型的、系统级编程语言。它被设计用于编写高性能、并发、安全的系统,并且可以避免常见的内存安全问题,如空指针和数据竞争。Rust的特点包括:零成本抽象、无运行时开销、内存安全、并发安全、线程安全、高性能等。

      1. Rust的语法有什么特点?

      Rust的语法类似于C++和其他系统级编程语言,但它也有一些独特的特点。例如,Rust使用模式匹配来处理变量赋值和函数参数等,这使得代码更加简洁、可读性更高。Rust还支持函数式编程范式,如闭包和函数式组合子。此外,Rust的类型系统非常强大,可以防止许多常见的编程错误。

      1. Rust的内存管理是如何工作的?

      Rust使用所有权和借用的概念来管理内存。所有权是指每个值都有一个所有者,只有它才能释放这个值。当值被移动到另一个所有者时,原来的所有者将失去对该值的访问权限。借用是指在不移动值的情况下,允许其他代码访问该值。Rust使用编译时的借用检查器来确保借用是安全的。

      1. Rust的并发编程有什么特点?

      Rust通过使用“通道”和“锁”等机制来实现并发编程。通道是一种线程间通信的机制,它允许线程之间发送和接收数据。锁是一种同步机制,它可以防止多个线程同时访问共享数据。Rust的并发编程还受益于其所有权和借用的内存管理机制,使得并发代码更加安全和清晰。

      1. Rust有哪些应用领域?

      Rust被广泛用于开发高性能、并发、安全的系统,如操作系统、网络编程、游戏引擎、嵌入式系统等。Rust还可以用于编写Web应用程序、命令行工具等。Rust的生态系统也非常丰富,有很多第三方库和框架可供使用。

      Rust VS Java

      1. 类型系统:Rust 是一门静态类型语言,Java 也是。不同的是,Rust 的类型系统更为严格,包括了所有权系统、借用检查、生命周期等概念,这使得 Rust 能够避免很多传统静态语言中的常见错误。Java 的类型系统相对简单,没有这些概念。

      2. 变量声明:Rust 的变量声明需要使用 let 关键字,而 Java 则是使用变量类型来声明。例如,Rust 中声明一个整型变量需要使用 let x: i32 = 10;,而 Java 中则是 int x = 10;。

      3. 函数定义:Rust 的函数定义需要使用 fn 关键字,而 Java 则是使用方法定义。Rust 中的函数可以有多个返回值,而 Java 中的方法只能返回一个值。此外,Rust 的函数参数可以指定类型,也可以使用泛型。

      4. 所有权和借用:Rust 中引入了所有权和借用的概念,用于管理内存资源。所有权是指变量拥有一块内存资源的权利,只有一个所有者,当所有者离开作用域时,内存资源会被释放。借用是指借用一个变量的引用,借用的引用必须在所有权范围内,否则就会出现错误。Java 没有这些概念,内存管理是由垃圾回收器来完成的。

      5. 包管理:Rust 的包管理使用 Cargo 工具,Java 的包管理使用 Maven 或者 Gradle。Cargo 的包管理方式更为简单,可以自动下载和管理依赖包,而 Maven 和 Gradle 则需要手动配置依赖。

      6. 并发编程:Rust 是一门并发编程友好的语言,它的并发编程模型使用了 Actor 模型。Java 的并发编程也很强大,使用 Thread、Executor、ForkJoin 等类来实现。Rust 中的并发编程更为安全,因为它的类型系统和所有权系统可以避免很多并发编程中的错误。

      总的来说,Rust 和 Java 的语法区别比较大,Rust 的类型系统更为严格,内存管理更为安全,同时具有良好的并发编程支持。Java 则更为简单易用,适合开发大型应用程序。

      Rust cargo

      Rust是一种由Mozilla开发的编程语言,专注于安全性、速度和并发性。Cargo是Rust的包管理器和构建工具,用于管理依赖项、构建和编译代码以及创建和发布软件包。

      Cargo还提供了一些其他功能,如测试、文档生成和依赖项更新等。它还允许您将软件包发布到https://crates.io/上,这是Rust的中央软件包仓库。这使得其他开发人员可以轻松地使用您的代码,并将其作为依赖项添加到他们自己的项目中。

      常用的Cargo命令及其描述如下:

      1. cargo new [name]:创建一个新的Rust项目
      2. cargo build:构建项目
      3. cargo run:运行项目
      4. cargo test:运行测试
      5. cargo doc:生成文档
      6. cargo update:更新依赖项
      7. cargo clean:清除构建输出
      8. cargo publish:将软件包发布到crates.io上
      9. cargo install [package]: 安装指定软件包
      10. cargo uninstall [package]: 卸载指定软件包

      除此之外,Cargo还有其他很多命令和选项,可以通过运行cargo --help或cargo [command] --help来获取更多信息。

      Rust变量

      在Rust中,变量是用于存储数据的命名存储空间。每个变量都有一个类型(type),用于指定变量可以存储的数据类型。

      定义变量可以使用let关键字,例如:

      let x = 10;
      let y: i32 = 20;
      

      在上述代码中,第一行定义了一个变量x,其类型会被编译器自动推断为i32类型。第二行定义了一个变量y,其类型被显式地指定为i32类型。

      需要注意的是,在Rust中,变量默认是不可变的,如果需要修改变量的值,必须将其定义为可变变量。例如:

      let mut z = 30;
      z = 40;
      

      在上述代码中,z被定义为可变变量,可以使用mut关键字进行标识。接着,z的值被修改为40。

      在Rust中,变量的作用域(scope)是通过大括号{}来定义的。在变量的作用域之外,变量就不再存在。例如:

      {
          let a = 1;
          println!("a = {}", a);
      }
      // a已经超出作用域,无法访问
      

      在上述代码中,a被定义在一个代码块中,只有在该代码块中才能访问。在代码块之外,a就不存在了。

      总之,变量是Rust中非常重要的概念,用于存储数据并进行计算。需要注意的是,Rust是一门静态类型语言,变量的类型必须在编译期确定,而且变量的作用域也需要明确地定义。

      Rust数据类型

      数据类型描述举例范围
      i8有符号8位整数let x: i8 = 42;-128 到 127
      i16有符号16位整数let x: i16 = 42;-32,768 到 32,767
      i32有符号32位整数let x: i32 = 42;-2,147,483,648 到 2,147,483,647
      i64有符号64位整数let x: i64 = 42;-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807
      i128有符号128位整数let x: i128 = 42;-170,141,183,460,469,231,731,687,303,715,884,105,728 到 170,141,183,460,469,231,731,687,303,715,884,105,727
      u8无符号8位整数let x: u8 = 42;0 到 255
      u16无符号16位整数let x: u16 = 42;0 到 65,535
      u32无符号32位整数let x: u32 = 42;0 到 4,294,967,295
      u64无符号64位整数let x: u64 = 42;0 到 18,446,744,073,709,551,615
      u128无符号128位整数let x: u128 = 42;0 到 340,282,366,920,938,463,463,374,607,431,768,211,455
      f32单精度浮点数let x: f32 = 3.14;精度为6-9位
      f64双精度浮点数let x: f64 = 3.14;精度为15-17位
      bool布尔类型let x: bool = true;true 或 false
      charUnicode字符类型let x: char = ‘A’;单个Unicode字符
      元组类型可包含不同类型的值let tup: (i32, f64, char) = (42, 3.14, ‘A’);-
      数组类型包含相同类型的值,长度固定let arr: [i32; 3] = [1, 2, 3];-
      引用类型用于引用其他值的指针类型let x: i32 = 42; let y: &i32 = &x;-

      Rust字符串

      在Rust中,字符串(string)是一种非常重要的数据类型,用于表示文本数据。Rust中的字符串有两种类型:String和&str。

      String类型是可变的、堆分配的字符串类型,可以动态地增加或删除字符。例如,下面创建了一个空的String对象,并使用push_str方法添加了一些字符:

      let mut s = String::new();
      s.push_str("hello");
      s.push_str(", world!");
      

      在上述代码中,使用String::new()方法创建了一个空的String对象,接着使用push_str方法向其添加了字符。

      另一种字符串类型是&str,它是不可变的、静态分配的字符串类型。&str通常是通过引用字符串字面量或String对象的方法来创建的。例如,下面使用字符串字面量创建了一个&str对象:

      let s = "hello, world!";
      

      需要注意的是,由于&str是不可变的,因此不能向其添加或删除字符。但是可以使用to_string方法将&str转换为String类型,从而实现字符串的动态修改:

      let s = "hello";
      let mut t = s.to_string();
      t.push_str(", world!");
      

      在Rust中,字符串的操作非常丰富,例如可以使用+运算符将两个字符串拼接起来,使用len方法获取字符串长度,使用chars方法获取字符串中的字符等。此外,Rust还提供了很多字符串处理的库,例如regex库用于处理正则表达式,serde_json库用于处理JSON数据等。

      总之,字符串在Rust中是一个非常重要的数据类型,具有丰富的操作和处理方式,可以用于解决各种问题,如文本处理、网络通信等。

      Rust Vec(可变数组)

      在 Rust 中,Vec 是一种动态大小的数组,可以在运行时添加或移除元素。与数组不同,Vec 的大小不是在编译时固定的,而是可以在运行时动态调整。Vec 的语法如下:

      let vec_name: Vec = vec![value1, value2, value3, ...];
      

      其中 vec_name 是向量的名称,type 是向量元素的类型,value1, value2, value3, ... 是向量的初始值。可以使用 vec![] 的语法来创建一个空的向量,例如:

      let mut v: Vec = Vec::new(); // 创建一个空向量
      v.push(1); // 向向量中添加元素
      v.push(2);
      

      上面的代码创建了一个空向量 v,然后使用 push 方法向向量中添加了两个元素。需要注意的是,因为向量是动态的,所以在使用之前需要声明为可变的(使用 mut 关键字)。

      向量的元素可以通过索引访问,索引从 0 开始。例如:

      let v = vec![1, 2, 3];
      println!("The third element is {}", v[2]);
      

      上面的代码定义了一个包含 3 个 i32 类型元素的向量,然后访问了第三个元素(索引为 2)。

      除了 push 方法,向量还提供了许多其他的方法,如 pop、insert、remove 等,可以对向量进行添加、删除、插入等操作。需要注意的是,由于向量是动态的,所以在删除或插入元素时,可能会导致向量重新分配内存,需要考虑性能问题。

      总的来说,向量是 Rust 中广泛使用的数据类型之一,可以用于存储和处理动态数据。与数组不同,向量可以动态调整大小,但也需要考虑内存分配和性能问题。

      Rust HashTable(Map)

      在Rust中,表(table)通常指的是哈希表(hash table),也称为字典(dictionary)、映射(map)等。哈希表是一种常用的数据结构,可以快速地查找和插入数据,其基本思想是通过哈希函数将键(key)映射到一个固定的位置,然后在该位置存储对应的值(value)。

      Rust标准库中提供了HashMap类型,用于表示哈希表。HashMap类型是泛型的,可以指定键(key)和值(value)的类型。例如,下面创建了一个HashMap,以String类型作为键,以i32类型作为值:

      use std::collections::HashMap;
      let mut scores = HashMap::new();
      scores.insert(String::from("Alice"), 100);
      scores.insert(String::from("Bob"), 90);
      

      在上述代码中,使用HashMap::new()方法创建了一个空的哈希表,接着使用insert方法向哈希表中插入数据。insert方法的第一个参数是键,第二个参数是值。

      可以使用.运算符来访问哈希表中的数据,例如scores.get("Alice")可以访问键为"Alice"的值。需要注意的是,由于哈希表可能会发生哈希冲突,因此在使用哈希表时需要考虑如何处理冲突。Rust标准库中的HashMap使用了开放地址法(open addressing)来解决冲突,同时也支持链表法(chaining)。

      除了HashMap类型外,Rust标准库中还提供了BTreeMap类型,用于表示有序哈希表。BTreeMap基于B树(B-tree)实现,可以在保持数据有序的同时快速地查找和插入数据。BTreeMap的使用方式与HashMap类似,只是需要注意键的类型必须实现Ord trait。

      总之,在Rust中,哈希表是一种非常常用的数据结构,可以用于解决各种问题,如缓存、索引等。Rust标准库提供了丰富的哈希表实现,可以满足各种需求。

      Rust逻辑判断

      在Rust中,逻辑判断主要使用if、else、match等关键字来实现。

      1. if语句

      if语句用于根据一个条件来执行不同的代码块。它的语法如下:

      if condition {
          // code block to execute if the condition is true
      } else {
          // code block to execute if the condition is false
      }
      

      其中,condition是一个返回布尔值的表达式。如果condition为true,则执行if代码块,否则执行else代码块。

      1. match语句

      match语句用于根据一个值的不同取值来执行不同的代码块。它的语法如下:

      match value {
          pattern1 => {
              // code block to execute if value matches pattern1
          },
          pattern2 => {
              // code block to execute if value matches pattern2
          },
          _ => {
              // code block to execute if value matches none of the patterns
          }
      }
      

      其中,value是要匹配的值,pattern1、pattern2等是匹配模式,用于指定不同的匹配情况。如果value匹配了其中的某个模式,则执行对应的代码块,否则执行_(下划线)模式对应的代码块。

      1. assert宏

      assert宏用于在代码中进行断言,即判断一个表达式是否为true。如果表达式为false,则程序会崩溃并输出错误信息。它的语法如下:

      assert!(expression);
      

      其中,expression是要进行断言的表达式。如果expression为false,则程序会崩溃并输出类似于“assertion failed: expression”这样的错误信息。

      Rust 循环

      Rust中有三种主要的循环结构:while、for和loop。下面是这三种循环的区别:

      1. while循环

      while循环用于在条件为真时重复执行代码块。它的语法如下:

      while condition {
          // code block to execute while the condition is true
      }
      

      其中,condition是一个返回布尔值的表达式。只要condition为true,就会重复执行while代码块。

      1. for循环

      for循环用于遍历一个集合或者一个范围内的值。它的语法如下:

      for variable in iterable {
          // code block to execute for each value in the iterable
      }
      

      其中,variable是一个变量,用于接收每个值。iterable是一个实现了Iterator trait的集合或者范围。对于每个值,都会执行一遍for代码块。

      1. loop循环

      loop循环用于无限循环执行代码块,直到手动中断。它的语法如下:

      loop {
          // code block to execute repeatedly until break is called
      }
      

      其中,loop代码块会一直重复执行,直到手动调用break语句中断循环。

      下表列出了这三种循环的区别:

      循环结构用途是否需要集合或范围是否需要手动中断
      while在条件为真时重复执行代码块
      for遍历一个集合或者一个范围内的值
      loop无限循环执行代码块,直到手动中断

      Rust结构

      在Rust中,结构(struct)是一种自定义的数据类型,用于存储不同类型的数据,并且可以自己定义结构的字段和方法。结构可以看做是一组相关的数据,可以通过名称来访问和操作这些数据。

      结构的定义使用关键字struct,并且需要给出结构的名称和字段。例如,下面定义了一个名为Person的结构,包含姓名和年龄两个字段:

      struct Person {
          name: String,
          age: u32,
      }
      

      在定义结构时,还可以为每个字段指定默认值,使用field: type = default_value的语法。例如,下面定义了一个名为Person的结构,包含姓名和年龄两个字段,其中年龄的默认值为0:

      struct Person {
          name: String,
          age: u32 = 0,
      }
      

      定义结构后,可以通过let关键字来创建结构的实例,并且为每个字段指定具体的值。例如,下面创建了一个名为person的Person结构实例:

      let person = Person {
          name: String::from("Alice"),
          age: 30,
      };
      

      通过.运算符可以访问结构中的字段,例如person.name即可访问person结构中的name字段。结构中的字段可以是任意类型,包括其他结构、枚举、标量类型、数组等等。

      除了字段外,结构还可以有方法(method),用于操作结构的数据。方法的定义使用关键字impl,并且需要给出方法所属的结构类型和方法的名称。例如,下面为Person结构定义了一个new方法,用于创建一个新的Person实例:

      impl Person {
          fn new(name: String, age: u32) -> Person {
              Person { name, age }
          }
      }
      

      在上述代码中,new方法的第一个参数是姓名,第二个参数是年龄。方法内部使用这两个参数来创建一个新的Person实例,并返回该实例。

      结构是Rust中非常常用的一种数据类型,通常用于表示真实世界中的概念,如人、车、房子等等。结构的定义和使用非常灵活,可以根据具体需求来自由组合。

      RustTrait(接口)

      在Rust中,接口被称为trait,是一种定义行为的方式。 trait定义了一组方法,这些方法可以被类型实现,使得这些类型能够表现出相同的行为。

      trait的定义方式与struct类似,使用关键字trait。例如:

      trait Fly {
          fn fly(&self);
      }
      

      在上述代码中,定义了一个名为Fly的trait,其定义了一个方法fly。这个方法接收一个self参数,表示对实现这个trait的类型的引用。

      接下来,可以为任何类型实现Fly trait,使得这些类型都具备fly方法。例如:

      struct Bird {}
      impl Fly for Bird {
          fn fly(&self) {
              println!("I can fly!");
          }
      }
      

      在上述代码中,定义了一个名为Bird的结构体,并为其实现了Fly trait。实现的具体方法是fly,用于实现Bird的飞行行为。

      最后,可以通过调用实现Fly trait的类型的fly方法来使用它。例如:

      let bird = Bird{};
      bird.fly();
      

      在上述代码中,创建了一个Bird类型的实例,然后调用了其fly方法,输出"I can fly!"。

      总之,trait是Rust中非常重要的概念,用于定义类型的行为。它们允许将行为与数据分离,使得代码更加模块化和可重用。

      Rust注解

      Rust的注解是以#字符开头的特殊注释,可以为代码提供更多的语义信息或者修改编译器的行为。Rust注解通常放在代码的上方,用于注释某些特定的语法结构或者代码块。下面是一些常用的Rust注解:

      1. #[derive(Debug)]:这个注解用于标记一个结构体或者枚举,让编译器自动生成Debug trait的实现。这样,在调试时,我们可以使用{:?}格式化输出结构体或者枚举的内容,方便快捷。

      2. #[test]:这个注解用于标记一个测试函数,表示它是一个单元测试。测试框架可以通过这个注解自动识别测试函数并执行测试,方便我们编写和运行测试代码。

      3. #[allow(unused_variables)]:这个注解用于关闭编译器的未使用变量警告。如果我们定义了一个变量但是并没有使用它,编译器会发出警告,这个注解可以帮助我们屏蔽这个警告。

      4. #[cfg(target_os = "windows")]:这个注解用于根据不同的操作系统编译不同的代码。如果我们的代码需要在不同的操作系统上运行,就可以使用这个注解来指定特定的编译条件。

      5. #[no_mangle]:这个注解用于防止Rust编译器对函数名进行重命名,保留原始名称。如果我们的代码需要和其他语言交互,就需要使用这个注解来保证函数名的一致性。

      总之,Rust注解可以提供额外的信息,帮助编译器和开发者更好地理解和处理代码,同时也可以修改编译器的行为,以满足特定的需求。

      Rust允许开发者自定义注解(Attribute),可以通过宏定义的方式实现。自定义注解可以为代码提供更多的语义信息,也可以修改编译器的行为,方便我们编写高效、优雅的代码。

      自定义注解的语法格式如下:

      #[my_attribute(arg1, arg2, ...)]
      fn my_function() {
          // code here
      }
      

      其中my_attribute是自定义注解的名称,arg1, arg2, ...是自定义注解的参数,它们可以是任何合法的Rust表达式。自定义注解的作用范围可以是函数、结构体、枚举、模块等。

      下面是一个自定义注解的例子:

      #[macro_export]
      macro_rules! my_macro {
          // macro definition here
      }
      

      这个例子中,macro_export是一个自定义注解,它的作用是将宏导出到当前模块的外部,方便其他模块使用。

      我们也可以自定义一个注解,例如:

      #[my_attribute("hello", 42)]
      fn my_function() {
          // code here
      }
      

      这里我们定义了一个名为my_attribute的注解,它带有两个参数:一个字符串"hello"和一个整数42。我们可以在函数内部使用这个注解,例如对函数进行标记,表示它是一个特定类型的函数。

      自定义注解的实现通常需要使用到宏定义,这超出了本文的范围,感兴趣的读者可以参考Rust官方文档中的相关内容。

      Rust模块

      在Rust中,模块是用于组织和管理代码的基本单元。模块可以包含函数、结构体、枚举、常量、trait等等。

      Rust的模块系统是基于文件系统的组织方式。每个Rust文件都可以被视为一个模块,模块名与文件名相同。在一个模块中,可以使用mod关键字定义子模块,使用use关键字引用其他模块中的定义。

      例如,假设有如下结构的文件系统:

      src/
      ├── main.rs
      └── my_module/
          ├── mod.rs
          ├── sub_module.rs
          └── my_struct.rs
      

      在上述结构中,src目录是Rust项目的根目录,main.rs是项目的入口文件。my_module目录是一个模块,其下有三个文件:

      • mod.rs:定义了my_module模块的公共接口。
      • sub_module.rs:定义了my_module模块的子模块sub_module。
      • my_struct.rs:定义了my_module模块的一个结构体MyStruct。

        在mod.rs中,可以使用mod关键字定义子模块,例如:

        mod sub_module;
        pub struct MyStruct {
            pub field: i32,
        }
        pub fn my_function() {
            println!("Hello from my_function!");
        }
        

        在上述代码中,定义了一个名为MyStruct的结构体,还有一个名为my_function的函数。同时,使用mod关键字定义了一个名为sub_module的子模块。

        在sub_module.rs中,可以定义子模块sub_module中的内容,例如:

        pub fn sub_function() {
            println!("Hello from sub_function!");
        }
        

        在上述代码中,定义了一个名为sub_function的函数。

        在使用my_module模块中的定义时,需要使用use关键字引用它们,例如:

        use crate::my_module::{MyStruct, my_function};
        use crate::my_module::sub_module::sub_function;
        fn main() {
            let my_struct = MyStruct { field: 42 };
            my_function();
            sub_function();
        }
        

        在上述代码中,使用use关键字引用了MyStruct和my_function,以及sub_function。然后,可以在main函数中使用这些定义。

        总之,Rust的模块系统是非常灵活和强大的,可以帮助开发者组织和管理大型项目的代码。同时,它也可以使得代码更加模块化和可重用。

        Rust Cargo.toml

        Rust使用 Cargo.toml 文件描述项目的元数据和依赖关系。下面是对 Cargo.toml 文件的详细讲解。

        Cargo.toml 文件是一个 TOML(Tom’s Obvious, Minimal Language,即Tom的简洁明了语言)格式的文件,用于描述 Rust 项目的元数据和依赖关系。它通常位于项目的根目录下,与 src/ 目录同级。

        下面是一个示例:

        [package]
        name = "myproject"
        version = "0.1.0"
        authors = ["Your Name "]
        edition = "2018"
        [dependencies]
        rand = "0.7.0"
        

        其中,[package] 表示包的元数据,包括包名、版本号、作者和 Rust 版本等信息。[dependencies] 表示包的依赖项,rand 是一个随机数生成器库,版本为 0.7.0。

        引入单个本地模块的方法是,在项目根目录下创建一个名为 src/ 的文件夹,然后在该文件夹下创建 Rust 模块,例如:

        // src/mymodule.rs
        pub fn myfunction() {
            println!("Hello, world!");
        }
        

        然后,在 main.rs(或其他程序入口文件)中引入该模块:

        // src/main.rs
        mod mymodule;
        fn main() {
            mymodule::myfunction();
        }
        

        引入多个本地模块也是类似的。假设在 src/ 目录下还有一个名为 myothermodule.rs 的 Rust 模块,可以这样写:

        // src/main.rs
        mod mymodule;
        mod myothermodule;
        fn main() {
            mymodule::myfunction();
            myothermodule::myotherfunction();
        }
        

        引入中央仓库的包依赖,则需要在 [dependencies] 部分添加相应的依赖项。例如,要添加一个名为 “serde” 的依赖项,可以这样写:

        [dependencies]
        serde = "1.0"
        

        这表示依赖的是 serde 库的 1.0 版本。Rust 的包管理器 Cargo 会自动从中央仓库(crates.io)下载该库,并将它作为项目的依赖项进行构建。

        下面是一个完整的 Cargo.toml 文件示例,包括引入多个本地模块和引入中央仓库的包依赖:

        [package]
        name = "myproject"
        version = "0.1.0"
        authors = ["Your Name "]
        edition = "2018"
        [dependencies]
        rand = "0.7.0"
        serde = "1.0"
        [lib]
        name = "mylib"
        path = "src/mylib.rs"
        [[bin]]
        name = "mybin"
        path = "src/mybin.rs"
        [[bin]]
        name = "myotherbin"
        path = "src/myotherbin.rs"
        [features]
        default = ["myfeature1"]
        myfeature1 = []
        myfeature2 = []
        [dependencies.mydependency]
        version = "1.0"
        features = ["myfeature1"]
        [workspace]
        members = [
            "mylib",
            "mybin",
            "myotherbin",
        ]
        

        其中,[lib] 表示库的配置,[[bin]] 表示可执行文件的配置,[features] 表示特性的配置,[dependencies.mydependency] 表示依赖的配置,[workspace] 表示工作空间的配置。这些配置的具体含义可以查看 Rust 官方文档。

        Rust常用库

        好的,以下是一些常用的 Rust 库及其常用方法的举例:

        1. std 库
        • println!(): 打印输出信息到控制台
        • Vec: 动态数组类型
        • String: 可变字符串类型
        • HashMap: 哈希表类型
          1. serde 库
          • serde_json::to_string(): 将 Rust 结构体序列化为 JSON 字符串
          • serde_json::from_str(): 将 JSON 字符串反序列化为 Rust 结构体
          • serde_yaml::to_string(): 将 Rust 结构体序列化为 YAML 字符串
          • serde_yaml::from_str(): 将 YAML 字符串反序列化为 Rust 结构体
            1. actix 库
            • actix_web::get(): 注册一个 GET 请求处理器
            • actix_web::post(): 注册一个 POST 请求处理器
            • actix_web::web::Json: 解析请求体中的 JSON 数据
              1. tokio 库
              • tokio::net::TcpListener: 创建一个 TCP 监听器
              • tokio::net::TcpStream: 创建一个 TCP 连接
              • tokio::spawn(): 在异步任务池中启动一个新的异步任务
                1. reqwest 库
                • reqwest::get(): 发送一个 GET 请求
                • reqwest::post(): 发送一个 POST 请求
                • reqwest::Client::new(): 创建一个 HTTP 客户端对象
                  1. rusoto 库
                  • rusoto_s3::S3Client::new(): 创建一个 AWS S3 客户端对象
                  • rusoto_ec2::Ec2Client::new(): 创建一个 AWS EC2 客户端对象
                  • rusoto_lambda::LambdaClient::new(): 创建一个 AWS Lambda 客户端对象
                    1. diesel 库
                    • diesel::prelude::*: 导入 Diesel 的预定义类型和函数
                    • diesel::insert_into(): 插入一条新的记录
                    • diesel::load(): 加载一组记录
                      1. log 库
                      • log::info(): 记录一条信息级别的日志
                      • log::error(): 记录一条错误级别的日志
                      • log::warn(): 记录一条警告级别的日志
                        1. rand 库
                        • rand::thread_rng(): 创建一个随机数生成器对象
                        • rand::Rng::gen_range(): 生成一个指定范围内的随机数
                        • rand::Rng::shuffle(): 随机打乱一个数组
                          1. image 库
                          • image::open(): 打开一个图像文件
                          • image::save(): 保存一个图像文件
                          • image::DynamicImage::resize(): 调整图像尺寸大小

                            以上是一些常用 Rust 库和方法的举例,当然还有很多其他的库和方法可以根据项目需求进行选择和使用。