第六章

  • 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

Packages and Crates

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 one or more crates that provide a set of functionality. A package contains a Cargo.toml file that describes how to build those crates.

Several rules determine what a package can contain. A package must contain zero or one library crates, and no more. It can contain as many binary crates as you’d like, but it must contain at least one crate (either library or binary).

A package contains:
- at least one crate (either library or binary);
- at most one library crate.

  • src/main.rs is the crate root of a binary crate with the same name as the package.
  • src/lib.rs is its crate root of of a library crate with the same name as the package.

If a package contains src/main.rs and src/lib.rs, it has two crates: a library and a binary, 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.

A crate will group related functionality together in a scope so the functionality is easy to share between multiple projects. For example, the rand crate we used in Chapter 2 provides functionality that generates random numbers. We can use that functionality in our own projects by bringing the randcrate into our project’s scope. All the functionality provided by the rand crate is accessible through the crate’s name, rand.

Keeping a crate’s functionality in its own scope clarifies whether particular functionality is defined in our crate or the rand crate and prevents potential conflicts. For example, the rand crate provides a trait named Rng. We can also define a struct named Rng in our own crate. Because a crate’s functionality is namespaced in its own scope, when we add rand as a dependency, the compiler isn’t confused about what the name Rng refers to. In our crate, it refers to the struct Rng that we defined. We would access the Rng trait from the rand crate as rand::Rng.

Defining Modules to Control Scope and Privacy

Modules let us organize code within a crate into groups for readability and easy reuse. Modules also control the privacy of items, which is whether an item can be used by outside code (public) or is an internal implementation detail and not available for outside use (private).

module tree

crate└── front_of_house├── hosting│   ├── add_to_waitlist│   └── seat_at_table└── serving├── take_order├── serve_order└── take_payment

Paths for Referring to an Item in the Module Tree

  • An absolute path starts from a crate root by using a crate name or a literal crate.
  • A relative path starts from the current module and uses self, super, or an identifier in the current module.

Both absolute and relative paths are followed by one or more identifiers separated by double colons (::).

mod front_of_house {mod hosting {fn add_to_waitlist() {}}
}pub fn eat_at_restaurant() {// Absolute pathcrate::front_of_house::hosting::add_to_waitlist();// Relative pathfront_of_house::hosting::add_to_waitlist();
}

Choosing whether to use a relative or absolute path is a decision you’ll make based on your project. The decision should depend on whether you’re more likely to move item definition code separately from or together with the code that uses the item. For example, if we move the front_of_house module and the eat_at_restaurant function into a module named customer_experience, we’d need to update the absolute path to add_to_waitlist, but the relative path would still be valid. However, if we moved the eat_at_restaurant function separately into a module named dining, the absolute path to the add_to_waitlist call would stay the same, but the relative path would need to be updated. Our preference is to specify absolute paths because it’s more likely to move code definitions and item calls independently of each other.

Modules aren’t useful only for organizing your code. They also define Rust’s privacy boundary: the line that encapsulates the implementation details external code isn’t allowed to know about, call, or rely on. So, if you want to make an item like a function or struct private, you put it in a module.

The way privacy works in Rust is that all items (functions, methods, structs, enums, modules, and constants) are private by default. Items in a parent module can’t use the private items inside child modules, but items in child modules can use the items in their ancestor modules. The reason is that child modules wrap and hide their implementation details, but the child modules can see the context in which they’re defined.

Rust chose to have the module system function this way so that hiding inner implementation details is the default. That way, you know which parts of the inner code you can change without breaking outer code. But you can expose inner parts of child modules’ code to outer ancestor modules by using the pub keyword to make an item public.

Exposing Paths with the pub Keyword

mod front_of_house {pub mod hosting {pub fn add_to_waitlist() {}}
}pub fn eat_at_restaurant() {// Absolute pathcrate::front_of_house::hosting::add_to_waitlist();// Relative pathfront_of_house::hosting::add_to_waitlist();
}

Starting Relative Paths with super

We can also construct relative paths that begin in the parent module by using super at the start of the path. This is like starting a filesystem path with the .. syntax.

fn serve_order() {}mod back_of_house {fn fix_incorrect_order() {cook_order();super::serve_order();}fn cook_order() {}
}

Making Structs and Enums Public

Enums aren’t very useful unless their variants are public; it would be annoying to have to annotate all enum variants with pub in every case, so the default for enum variants is to be public. Structs are often useful without their fields being public, so struct fields follow the general rule of everything being private by default unless annotated with pub.

Bringing Paths into Scope with the use Keyword

Adding use and a path in a scope is similar to creating a symbolic link in the filesystem.

You can also bring an item into scope with use and a relative path.

Creating Idiomatic use Paths

Bringing the function’s parent module into scope with use so we have to specify the parent module when calling the function makes it clear that the function isn’t locally defined while still minimizing repetition of the full path.

On the other hand, when bringing in structs, enums, and other items with use, it’s idiomatic to specify the full path.

use std::collections::HashMap;fn main() {let mut map = HashMap::new();map.insert(1, 2);
}

Providing New Names with the as Keyword

mod front_of_house {pub mod hosting {pub fn add_to_waitlist() {}}
}use crate::front_of_house::hosting;pub fn eat_at_restaurant() {hosting::add_to_waitlist();hosting::add_to_waitlist();hosting::add_to_waitlist();
}
use std::fmt;
use std::io;fn function1() -> fmt::Result {// --snip--
}fn function2() -> io::Result<()> {// --snip--
}
use std::fmt::Result;
use std::io::Result as IoResult;fn function1() -> Result {// --snip--
}fn function2() -> IoResult<()> {// --snip--
}

Re-exporting Names with pub use

mod front_of_house {pub mod hosting {pub fn add_to_waitlist() {}}
}pub use crate::front_of_house::hosting;pub fn eat_at_restaurant() {hosting::add_to_waitlist();hosting::add_to_waitlist();hosting::add_to_waitlist();
}

By using pub use, external code can now call the add_to_waitlist function using hosting::add_to_waitlist. If we hadn’t specified pub use, the eat_at_restaurant function could call hosting::add_to_waitlist in its scope, but external code couldn’t take advantage of this new path.

Using External Packages

Using Nested Paths to Clean Up Large use Lists

If we’re using multiple items defined in the same package or same module, listing each item on its own line can take up a lot of vertical space in our files.
Instead, we can use nested paths to bring the same items into scope in one line. We do this by specifying the common part of the path, followed by two colons, and then curly brackets around a list of the parts of the paths that differ.
We can use a nested path at any level in a path, which is useful when combining two use statements that share a subpath.

use std::io;
use std::io::Write;
use std::io::{self, Write};

The Glob Operator

If we want to bring all public items defined in a path into scope, we can specify that path followed by *, the glob operator:

use std::collections::*;

Separating Modules into Different Files

Using a semicolon after mod front_of_house rather than using a block tells Rust to load the contents of the module from another file with the same name as the module.

Rust lets you split a package into multiple crates and a crate into modules so you can refer to items defined in one module from another module. You can do this by specifying absolute or relative paths. These paths can be brought into scope with a use statement so you can use a shorter path for multiple uses of the item in that scope. Module code is private by default, but you can make definitions public by adding the pub keyword.

Rust自学笔记 | Packages Crates Modules相关推荐

  1. JavaWeb自学笔记(一)

    JavaWeb自学笔记(一) 学习视频:BV12J411M7Sj 文章目录 JavaWeb自学笔记(一) 1.基本概念 1.1 web应用程序 1.2 静态web 1.3 动态web 2.web服务器 ...

  2. pytorch自学笔记

    pytorch和tensorflow是机器学习的两大框架,上一篇帖子已经完整梳理了TensorFlow自学的知识点,这一篇把自学pytorch的知识点也整理下来,内容参考了网上很多帖子,不一一引用了, ...

  3. Scrapy 小白自学笔记

    Scrapy 小白自学笔记 Scrapy 小白自学笔记 Scrapy环境搭建 安装scrapy pip install scrapy 安装pywin32 D:>pip install pywin ...

  4. Android开发自学笔记—1.1(番外)AndroidStudio常用功能介绍

    Android开发自学笔记-1.1(番外)AndroidStudio常用功能介绍 http://www.cnblogs.com/boyliupan/p/4729736.html#_labelTop 回 ...

  5. 字节跳动大佬的Python自学笔记.pdf

    1. 字节跳动大佬的Python自学笔记 这是我的一个朋友自学资料包,通过这个资料包自学拿到了字节跳动的Offer, 下面是他之前入门学习Python时候的学习资料,非常全面,从Python基础.到w ...

  6. JAVA自学笔记07

    JAVA自学笔记07 1.构造方法 1) 例如:Student s = new Student();//构造方法 System.out.println(s);// Student@e5bbd6 2)功 ...

  7. MySQL自学笔记2--select的5个子句

    MySQL自学笔记 使用的MySQL自带命令客户端,其中具体的操作是在自建的数据库下room303表中进行的,表中的列有:id.name.age.email.tel.salary.riqi.class ...

  8. JAVA自学笔记24

    JAVA自学笔记24 1.能使用同步代码块就使用同步代码块,除非锁对象是this,就可以考虑使用同步方法.静态方法的锁是类的字节码对象. 2.JDK5新特性 1)接口Lock void Lock()/ ...

  9. 怎么用vc采集ni卡数据_SystemLink自学笔记(6):SystemLink架构和数据服务

    1. SystemLink架构和数据服务 1.1. 架构和特点 现在在对SystemLink的功能有了一个大概的了解后,可以进一步从它的整体架构学习这门新技术了.NI官网给出了白皮书,原文是英文资料, ...

最新文章

  1. 手把手教 | 使用Keras构造日文的神经网络语言模型(内附源码)
  2. 数组怎么用getchar_C语言 | 数组
  3. BZOJ.3277.串(广义后缀自动机)
  4. 全国计算机等级考试题库二级C操作题100套(第63套)
  5. 怎么做一张优雅的数据源监控报表
  6. Linux基础(2)-基础命令和bash的基础特性(1)
  7. hadoop 主要配置文件
  8. 求字符串长度(复习)
  9. ORACLE利用scn赚钱,在Oracle中增进SCN及案例介绍
  10. python numpy模块玩转矩阵与科学计算
  11. pip安装tensorflow_Tensorflow源代码编译踩坑若干
  12. 多媒体技术是指运用计算机,多媒体技术的概念与应用
  13. Uploadify-中文帮助手册
  14. 20175212童皓桢 《Java程序设计》第六周学习总结
  15. GSM与GPRS区别介绍
  16. 2018年中国游戏行业发展现状及发展前景分析
  17. MIT 6.824学习-GFS
  18. 虚荣登陆显示无法连接服务器,虚荣服务器连接不上怎么办?连接服务器解决办法...
  19. centos6.4下安装fetion
  20. 中欧基金窦玉明:资管机构进阶之道

热门文章

  1. Krpano 随笔 (一) 基本使用
  2. 《【西天取经】Go语言学习笔记:基本变量与类型》
  3. VB超级模块函数:VB读写记事本-防止乱码支持UTF-8和GB2312编码
  4. Python3.根据ID3v2批量修改mp3文件名
  5. 入职中国平安三周年的一些总结
  6. 【虹科终端安全案例】工业机器人领先企业Yaskawa Motoman如何应对高级威胁?
  7. JAVA多态机制简述
  8. guns常用功能整理
  9. 数据库10.12水费管理系统相关表格设计.....修改
  10. 二叉树非递归后序遍历算法的一种简单思路