☰
《Rust程序设计》学习笔记七:crate与模块
2026/10/13 7:04:23 网站建设 项目流程

===^^===
下面是介绍《榴芒客服系统》的博客,它是我们工作室开发的在线客服系统,欢迎下载试用:
https://blog.csdn.net/look4liming/article/details/164755808https://blog.csdn.net/look4liming/article/details/164755808

Rust程序由crate组成。每个crate都是既完整又内聚的单元,包括单个库或可执行程序的所有源代码,以及任何相关的测试、示例、工具、配置和其它杂项。

Rust具有极强的兼容性保证。任何能在低版本Rust上编译的代码在更高版本的Rust上都必然编译得一样好。

但有时候会有一些必要的扩展提议加入语言中,这有可能导致就代码无法再编译。Rust确定了一种支持异步編程的语法,该语法将标识符async和await重新用作关键字。这种语法更改会破坏任何使用async和await作为变量名的现有代码。

每个crate都在其Cargo.toml文件顶部的[package]部分使用下面这样的行来表明自己是用哪个版本的Rust编写的:

edition = "2021"

crate的版本只影响其源代码的解释方式,编译代码时,版本的差异已然消失。

crate是关于项目间代码共享的,模块是关于项目内代码组织的。它们扮演着Rust命名空间的角色,是构成Rust程序或库的函数、类型、常量等的容器。

mod spores {

use cells::{Cell, Gene};

pub struct Spore {

// ...

}

pub fn produce_spore(factory: &mut Sporangium) -> Spore {

// ...

}

pub(crate) fn genes(spore: &Spore) -> Vec<Gene> {

// ...

}

fn recombine(parent: &mut Cell) {

// ...

}

// ...

}

模块是一组语法项的集合。

把函数标记为pub(crate),那么就意味着它可以在这个crate中的任何地方使用,但不会作为外部接口的一部分公开。它不能被其他crate使用,也不会出现在这个crate的文档中。

未标记为pub的内容都是私有的,只能在定义它的模块及其任意子模块中使用。

将某个语法项标记为pub通常称为“导出”该语法项。

模块可以嵌套:

mod plant_structures {

pub mod roots {

// ...

}

pub mod stems {

// ...

}

pub mod leaves {

// ...

}

}

如果希望嵌套模块中的语法项对其它crate可见,请务必将它和它所在的模块编辑为公开的(pub)。

可以指定pub(super),让语法项支队其父模块可见。

还可以指定pub(in <path>),让语法项在特定的父模块及其后代中可见:

mod plant_structures {

pub mod roots {

pub mod products {

pub(in crate::plant_structures::roots) struct Cytokinin {

// ...

}

}

use products::Cytokinin; // 正确,在roots模块中可见

}

// 错误,Cytokinin是私有的:

use plant_structures::roots::products::Cytokinin;

}

模块还可以像下面这样写:

mod spores;

这条语句告诉Rust编译期,spores模块保存在一个单独的名为spores.ts的文件中。

模块可以有自己的目录。当Rust看到mod spore;时,会同时检查spores.rs和spores/mod.rs,如果两个文件都不存在,或者都存在,就会报错。

在main.rs中,声明了plant_structures模块:

pub mod plant_structures;

这样,Rust会加载plant_structures/mod.rs,该文件声明了3个子模块:

pub mod roots;

pub mod stems;

pub mod leaves;

这3个模块的内容存储在leaves.rs、roots.rs和stems.rs这3个单独的文件中,与mod.rs一样位于plant_structures目录下。

::运算符用于访问模块中的各项特征。

use std::mem;

if s1 > s2 {

mem::swap(&mut s1, &mut s2);

}

这条use声明导致名称mem在整个封闭块或模块中成了std::mem的本地别名。

可以一次导入多个名称:

// 同时导入两个模块:

use std:collections::{HashMap, HashSet};

// 同时导入std::fs和std::fs::File:

use std::fs::(self, File);

// 导入所有语法项:

use std::io::prelude::*;

使用as关键字导入一个语法项,但在本地赋予它一个别名:

use std::io::Result as IOResult;

模块不会自动从其父模块集成名称。假设proteins/mod.rs中有如下代码:

pub enum AminoAcid { ... }

pub mod synthesis;

那么synthesis.rs中的代码不会自动“看到”类型AminoAcid:

pub fn synthesize(seq: &[AminoAcid]) // 错误,找不到类型AminoAcid!

子模块可以使用use super::*访问其父模块中的私有语法项。

绝对路径以::开头,总会引用外部crate:

use ::image::Pixels;

要引用自己模块中的Sampler类型,可以这样写:

use self::image::Sampler;

模块与文件不是一回事,但模块与Unix文件系统中的目录和文件有些相似之处。self和super类似于.和..这样的特殊目录。

Rust的行为就好像每个模块(包括根模块)都用以下导入语句开头一样:

use std::prelude::v1::*;

虽然use声明只是个别名,但也可以公开它们:

// 在plant_structures/mod.rs中:

...

pub use self::leaves::Leaf;

pub use self::roots::Root;

...

这意味着Leaf和Root是plant_structures模块的公共语法项。它们还是plant_structures::leaves::Leaf和plant_structures::roots::Root的简单别名。

结构体的字段,甚至是私有字段,都可以在声明该结构体的整个模块及其子模块中访问。在模块之外,只能访问公共字段。

除了函数、类型和嵌套模块,模块中还可以定义常量和静态变量。

关键字const用于引入常量,其语法和let一样,只是它可以标记为pub,并且必须写明类型:

pub const ROOM_TEMPERATURE: f64 = 20.0;

static关键字引入静态语法项,跟常量几乎是一回事:

pub static ROOM_TEMPERATURE: f64 = 68.0;

常量有点像C++中的#define,该值在每个使用了它的地方都会编译到代码中。静态变量是在程序开始运行之前设置并持续到程序退出的变量。

没有mut常量。静态变量可以标记为mut,Rust没有办法强制执行其关于mut静态变量的独占访问规则,因此,mut静态变量本质上是非线程安全的,安全代码根本不能使用它们:

static mut PACKETS_SERVED: usize = 0;

println!("{} served", PACKETS_SERVED); // 错误,使用了mut静态变量。

Rust不鼓励使用全局可变状态。

和内容把程序变成库,步骤如下:

1、将文件src/main.rs重命名为src/lib.rs;

2、将pub关键字添加到src/lib.rs中的语法项上,这些语法项将成为这个库的公共特性。

3、将main函数移动到某个临时文件中。

不需要更改Cargo.toml中的任何内容。默认设定下,cargo build会查看源目录中的文件并根据文件名确定要构建的内容。当它发现存在文件src/lib.rs时,就知道要构建一个库。

src/lib.rs中的代码构成了库的根模块。其它使用这个库的crate只能访问这个根模块的公共语法项。

Cargo会自动将src/bin中的.rs文件视为应该构建的额外程序。

还可以利用子目录在src/bin目录中构建更大的程序。

Rust程序中的任何语法项都可以用属性进行修饰。属性是Rust的通用语法,用于向编译期提供各种指令和建议。

告诉Cargo从哪里获取项目所依赖的crate源代码的一种方法,通过版本号:

image = "0.6.1"

使用没有发布在crates.io上的依赖项,一种方法是指定Git存储库URL和修订号:

image = {git = "https://.../image.git", rev = "528f19c"}

另一种方法是指定源代码目录:

image = {path = "vendor/image"}

===^^===
下面是介绍《榴芒客服系统》的博客,它是我们工作室开发的在线客服系统,欢迎下载试用:
https://blog.csdn.net/look4liming/article/details/164755808https://blog.csdn.net/look4liming/article/details/164755808

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询