Rust 学习之旅(7):Package,Crate,Module
Rust 学习之旅(7):Package,Crate,Module
这是第 7 章的读书笔记,Cargo Workspace 在第 14 章。
Packages and Crates
As a project grows, you should organize code by splitting it into multiple modules and then multiple files. A package can contain multiple binary crates and optionally one library crate. As a package grows, you can extract parts into separate crates that become external dependencies.
随着项目的增长,你需要通过把代码分离到不同的模块,不同的文件来管理代码。一个包(Package)可以有多个可执行文件(Binary Crate),和一个可选的 Library Crate。随着这个包的增长,还可以把包的一部分变成一个外部依赖。
Rust 的模块系统(Module System)有很多的特性:
- Packages: A Cargo feature that lets you build, test, and share crates
- Crates: A tree of modules that produces a library or executable
- Modules and use: Let you control the organization, scope, and privacy of paths
- Paths: A way of naming an item, such as a struct, function, or module
A crate is the smallest amount of code that the Rust compiler considers at a time. Even if you run rustc
rather than cargo
and pass a single source code file (as we did all the way back in the “Writing and Running a Rust Program” section of Chapter 1), the compiler considers that file to be a crate. Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections.
Rust 编译器一次考虑一个 Crate。如果使用 rustc
编译单个 .rs 文件,编译器会认为这个 .rs 文件就是一个 Crate。Crate 里面可以有很多的模块,这些模块可以在不同的文件里面。一个 Crate 可以是一个可执行的文件(Binary Crate)或者库(Library Crate)。Binary Crate 必须有一个 main 函数,Library Crate 不能有 main 函数。
A crate can come in one of two forms: a binary crate or a library crate. Binary crates are programs you can compile to an executable that you can run, such as a command-line program or a server. Each must have a function called main
that defines what happens when the executable runs.
Library crates don’t have a main function, and they don’t compile to an executable. Instead, they define functionality intended to be shared with multiple projects. For example, the rand crate we used in Chapter 2 provides functionality that generates random numbers. Most of the time when Rustaceans say “crate”, they mean library crate, and they use “crate” interchangeably with the general programming concept of a “library".
Rustacean 所说的这个 Crate,就相当于说是库。
The crate root is a source file that the Rust compiler starts from and makes up the root module of your crate.
A package is a bundle of one or more crates that provides a set of functionality. A package contains a Cargo.toml file that describes how to build those crates. Cargo is actually a package that contains the binary crate for the command-line tool you’ve been using to build your code. The Cargo package also contains a library crate that the binary crate depends on. Other projects can depend on the Cargo library crate to use the same logic the Cargo command-line tool uses.
一个包就是一个或者多个 Crate 绑在一起。一个 Package 包含一个 Cargo.toml 描述如何去构建这些 crate。Cargo 实际上是一个包,Cargo 有作为命令行工具它得提供 Binary Crate,此外 Cargo 也包含了它的 Binary Crate 所依赖的 Library Crate。
A package can contain as many binary crates as you like, but at most only one library crate. A package must contain at least one crate, whether that’s a library or binary crate.
一个包,就是我们用 cargo 创建的项目,可以有很多的 Binary Crate,也就是说我们新建了一个项目,我们可以构建多个可执行的文件,但是最多只能有一个 Library Crate。我们创建了一个包,当然是希望这个包是一个库或者这个包是可以为我们生成可执行的文件,所以我们创建一个包,这个包至少得有一个 Crate,要么是一个 Binary Crate,要么是 Library Crate。
一个 Package 里面有我们的依赖和库,依赖是 Crate,自己写的一个或者好几个代码文件组成的也是一个 Crate。当我们使用 cargo 创建一个项目的时候,它会提示说 Created ... package。所以我们创建一个项目的时候实际上就是新建了一个包。
$ cargo new my-project
Created binary (application) `my-project` package
$ ls my-project
Cargo.toml
src
$ ls my-project/src
main.rs
我们常说 C/C++ 的编译器一次考虑一个编译单元,而 Rust 一次考虑一个 Crate,从 Crate Root 开始找这个 Crate 要哪些东西。
In the project directory, there’s a Cargo.toml file, giving us a package. There’s also a src directory that contains main.rs. Open Cargo.toml in your text editor, and note there’s no mention of src/main.rs. Cargo follows a convention that src/main.rs is the crate root of a binary crate with the same name as the package. Likewise, Cargo knows that if the package directory contains src/lib.rs, the package contains a library crate with the same name as the package, and src/lib.rs is its crate root. Cargo passes the crate root files to rustc
to build the library or binary.
Cargo.toml 里面没有提到 src/main.rs。Cargo 遵循一个惯例:src/main.rs 是默认的 Binary Crate 的 crate root,这个 Binary Crate 的名字和包的名字一样。src/lib.rs 是默认的 Library Crate 的 crate root,这个 Library Crate 的名字和包的名字一样。Cargo 把 crate root 文件传给 rustc 去构建库或者可执行的。
If a package contains src/main.rs and src/lib.rs, it has two crates: a binary and a library, both with the same name as the package. A package can have multiple binary crates by placing files in the src/bin directory: each file will be a separate binary crate.
一个包里面有 src/main.rs 和 src/lib.rs,意味着这个包有两个 crate,分别是 binary crate 和 library crate。这俩 crate 的名字都是包的名字。一个包可以有多个 binary crate 放在 src/bin 目录下。每个文件都是一个单独的 binary crate。
7.1 小结
cargo 创建的项目实际上就是一个包,一个项目里面可以依赖别的库,Rustacean 通常把库称作 crate。我们创建一个项目可以生产多个可执行的文件,src/main.rs 是默认和包名(项目名)同名的可执行文件。其余的可执行文件的代码可以放在 src/bin 目录下。crate 并不是单个代码文件,crate 是 Rust 编译器一次考虑的代码们。Crate 可能是涉及到多个代码文件的。不过一个包里面只能有一个库,我们的 package 里面只能有一个 library crate。我们通常就是在造 Crate,如果希望执行一个 Crate 做些事情就造一个 Binary Crate,如果希望造个 Crate 给别人用就造个 Library Crate。
Defining Modules to Control Scope and Privacy
第 7 章讲模块系统,当然是要有模块的。模块系统就是控制作用域和名字空间。
Modules Cheat Sheet
Here we provide a quick reference on how modules, paths, the use
keyword, and the pub keyword work in the compiler, and how most developers organize their code. We’ll be going through examples of each of these rules throughout this chapter, but this is a great place to refer to as a reminder of how modules work.
- Start from the crate root: When compiling a crate, the compiler first looks in the crate root file (usually src/lib.rs for a library crate or src/main.rs for a binary crate) for code to compile.
- Declaring modules: In the crate root file, you can declare new modules; say, you declare a “garden” module with
mod garden;
. The compiler will look for the module’s code in these places:- Inline, within curly brackets that replace the semicolon following
mod garden
- In the file src/garden.rs
- In the file src/garden/mod.rs
- Inline, within curly brackets that replace the semicolon following
- Declaring submodules: In any file other than the crate root, you can declare submodules. For example, you might declare
mod vegetables;
in src/garden.rs. The compiler will look for the submodule’s code within the directory named for the parent module in these places:- Inline, directly following
mod vegetables
, within curly brackets instead of the semicolon - In the file src/garden/vegetables.rs
- In the file src/garden/vegetables/mod.rs
- Inline, directly following
- Paths to code in modules: Once a module is part of your crate, you can refer to code in that module from anywhere else in that same crate, as long as the privacy rules allow, using the path to the code. For example, an
Asparagus
type in the garden vegetables module would be found atcrate::garden::vegetables::Asparagus
. - Private vs public: Code within a module is private from its parent modules by default. To make a module public, declare it with
pub mod
instead ofmod
. To make items within a public module public as well, usepub
before their declarations. - The
use
keyword: Within a scope, the use keyword creates shortcuts to items to reduce repetition of long paths. In any scope that can refer tocrate::garden::vegetables::Asparagus
, you can create a shortcut withuse crate::garden::vegetables::Asparagus;
and from then on you only need to writeAsparagus
to make use of that type in the scope.
除了 Crate 之外,其他的代码文件都是模块(Module)。使用文件系统类似的路径的组织模块,模块可以直接写在一个代码文件里面,也可以放在单独的文件,大一点的模块可以放在一个目录里面。
Grouping Related Code in Modules
Modules let us organize code within a crate for readability and easy reuse. Modules also allow us to control the privacy of items, because code within a module is private by default. Private items are internal implementation details not available for outside use. We can choose to make modules and the items within them public, which exposes them to allow external code to use and depend on them.
一个 crate 内的代码,通过模块化的组织可以增强可读性,更容易重用。模块允许我们控制私有的项,因为模块内的代码默认就是私有的(private)。私有代码的实现细节是不对外公开的。我们可以选择公开模块内的代码,把模块内的代码暴露给外部使用。
整个模块树的根有个名字:crate。
7.2 小结
我们的目的是生产 Crate,为了更好的管理和生产 Crate,我们把 Crate 相关的东西划分成模块。就像组装木条箱子,我们整理好木条箱子的上下的板子,再整理好前后左右的板子再拼接起来。至于那块板子是铁的还是木头的,有没有加块布或者皮包起来不重要,重要的是,我们要组装箱子,我们拿箱子的各个部分来组装就行了。(我也没干过木工,不知道咋干的)
Paths for Referring to an Item in the Module Tree
A path can take two forms:
- An absolute path is the full path starting from a crate root; for code from an external crate, the absolute path begins with the crate name, and for code from the current crate, it starts with the literal
crate
. - A relative path starts from the current module and uses
self
,super
, or an identifier in the current module.
super 引用父级作用域,crate 是 Crate Root。
7.3 和 7.4 小节主要是用法,直接看书上的例子就行。
Separating Modules into Different Files
7.5 小节讲如何把一个大的模块分到不同文件。
Note that you only need to load a file using a mod declaration once in your module tree. Once the compiler knows the file is part of the project (and knows where in the module tree the code resides because of where you’ve put the mod statement), other files in your project should refer to the loaded file’s code using a path to where it was declared, as covered in the “Paths for Referring to an Item in the Module Tree” section. In other words, mod is not an “include” operation that you may have seen in other programming languages.
在 module tree 里面加载一个模块只需要用 mod 声明一次,其他的文件引用这个模块使用声明的路径。换句话说,mod 不是其他语言里面的 include。其他的文件要引用这个模块是通过这个模块树的路径,而不是把这个模块重新 include 一次。C++ 20 新特性 Modules。
7.5小结
最重要的是弄清楚 Rust 模块系统的术语。Rust 可以把一个包分成多个 Crate,一个 Crate 可以分成多个模块,模块之间可以互相引用。模块代码默认是私有的,可以使用 pub 关键字公开。
Rust 学习之旅(7):Package,Crate,Module的更多相关文章
- rust 学习之旅二,关键字和保留字
当前,以下关键字具有所描述的功能. as-执行原始类型转换,消除包含项目的特定特征的歧义,或在useand extern crate语句中重命名项目async-返回a Future而不是阻塞当前线程a ...
- rust 学习之旅一, rust编程环境相关
Mac rust环境 rust安装: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh rust更新: rustup upd ...
- Lua 学习之基础篇七<Lua Module,Package介绍>
Lua 之Module介绍 包管理库提供了从 Lua 中加载模块的基础库. 只有一个导出函数直接放在全局环境中: [require]. 所有其它的部分都导出在表 package 中. require ...
- 滴滴Booster移动APP质量优化框架 学习之旅 二
推荐阅读: 滴滴Booster移动App质量优化框架-学习之旅 一 Android 模块Api化演练 不一样视角的Glide剖析(一) 续写滴滴Booster移动APP质量优化框架学习之旅,上篇文章分 ...
- Hadoop学习之旅二:HDFS
本文基于Hadoop1.X 概述 分布式文件系统主要用来解决如下几个问题: 读写大文件 加速运算 对于某些体积巨大的文件,比如其大小超过了计算机文件系统所能存放的最大限制或者是其大小甚至超过了计算机整 ...
- Hadoop学习之旅三:MapReduce
MapReduce编程模型 在Google的一篇重要的论文MapReduce: Simplified Data Processing on Large Clusters中提到,Google公司有大量的 ...
- 我的angularjs源码学习之旅2——依赖注入
依赖注入起源于实现控制反转的典型框架Spring框架,用来削减计算机程序的耦合问题.简单来说,在定义方法的时候,方法所依赖的对象就被隐性的注入到该方法中,在方法中可以直接使用,而不需要在执行该函数的时 ...
- 180分钟的python学习之旅
最近在很多地方都可以看到Python的身影,尤其在人工智能等科学领域,其丰富的科学计算等方面类库无比强大.很多身边的哥们也提到Python非常的简洁方便,比如用Django搭建一个见得网站只需要半天时 ...
- 【转】基于 Android NDK 的学习之旅-----数据传输(引用数据类型)
原文网址:http://www.cnblogs.com/luxiaofeng54/archive/2011/08/20/2147086.html 基于 Android NDK 的学习之旅-----数据 ...
- AngularJS学习之旅—AngularJS 模块(十五)
一.AngularJS 模块 模块定义了一个应用程序. 模块是应用程序中不同部分的容器. 模块是应用控制器的容器. 控制器通常属于一个模块. 1.创建模块 通过 AngularJS 的 angular ...
随机推荐
- 第六章:Django 综合篇 - 7:网站地图sitemap
网站地图是根据网站的结构.框架.内容,生成的导航网页,是一个网站所有链接的容器.很多网站的连接层次比较深,蜘蛛很难抓取到,网站地图可以方便搜索引擎或者网络蜘蛛抓取网站页面,了解网站的架构,为网络蜘蛛指 ...
- TCP服务端收到syn但是不回复syn ack问题分析
文章转载自:https://blog.csdn.net/jueshengtianya/article/details/52130667 最近在分析客户的一个问题时遇到了一种奇怪的情况,客户在服务端开启 ...
- 天天向上力量B
N=eval(input()) up=pow(1+0.001*N,365) down=pow(1-0.001*N,365) print("{:.2f}, {:.2f}, {:.0f}&quo ...
- css 悬停图片改变图片的样式
<style> #div{ text-align: center; } .img{ width: 200px; clip-path: polygon(50% 0,100% 50%,50% ...
- ETL工具Datax、sqoop、kettle 的区别
一.Sqoop主要特点: 1.可以将关系型数据库中的数据导入到hdfs,hive,hbase等hadoop组件中,也可以将hadoop组件中的数据导入到关系型数据库中: 2.sqoop在导入导出数据时 ...
- POJ1741 tree (点分治模板)
题目大意: 给一棵有 n 个顶点的树,每条边都有一个长度(小于 1001 的正整数).定义 dist(u,v)=节点 u 和 v 之间的最小距离.给定一个整数 k,对于每一对 (u,v) 顶点当且仅当 ...
- strut2 标签加载图表。
//===============================================超市订单量走势图========================================= v ...
- 5.MongoDB系列之索引(二)
1. $运算符如何使用索引 1.1 低效的运算符 $ne.$not查询可以使用索引,但不是很有效,尽量避免 1.2 范围查询 范围查询其实是多值查询,根据复核索引规则,尽可能先等值精确匹配,然后范围查 ...
- 常用排序算法(C语言)
1.冒泡排序 void BubbleSort(int a[],int len) {int tmp; for (int i=0; i<n-1; i++) { int flag = FALSE; f ...
- nrf9160做modem——测试连接阿里云
简介:在前面有讲过如何使用nrf9160去连接一个云,然后进行发布订阅信息,但是当时连接的是一个免费的测试云,在国内的话许多人想要连接阿里云或者华为云,下面就来测试一下连接阿里云.这里为什么要和上一篇 ...