使用 use 关键字引入路径

每次调用函数时都必须写出完整路径,可能会感觉不便且重复。在清单7-7中,无论我们选择绝对路径还是相对路径来调用 add_to_waitlist 函数,每次调用时都必须指定 front_of_house 和 hosting。幸运的是,有一种简化此过程的方法:我们可以用 use 关键字为某个路径创建一个快捷方式,然后在作用域内的其他地方使用更短的名称。

在清单7-11中,我们将 crate::front_of_house::hosting 模块引入到 eat_at_restaurant 函数的作用域内,因此只需指定 hosting::add_to_waitlist 即可在 eat_at_restaurant 中调用 add_to_waitlist 函数。

文件名:src/lib.rs

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();  
}  

清单7-11:使用 use 将模块引入作用域
在作用域中添加 use 和一个路径类似于在文件系统中创建符号链接。通过在 crate 根目录添加 use crate::front_of_house::hosting,hosting 就成为该作用域中的有效名称,就好像 hosting 模块定义在 crate 根目录一样。通过 use 引入的路径同样会检查隐私权限,与其他任何路径一样。

注意,use 仅为其所在的特定作用域创建快捷方式。清单7-12将 eat_at_restaurant 函数移动到名为 customer 的新子模块,这与 use 声明所在的作用域不同,因此函数体无法编译。

文件名:src/lib.rs

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

清单7-12:use 语句仅适用于其所在的作用域。
编译器错误显示该快捷方式不再适用于 customer 模块:

$ cargo buildCompiling restaurant v0.1.0 (file:///projects/restaurant)
error[E0433]: failed to resolve: use of undeclared crate or module `hosting`--> src/lib.rs:11:9|
11 |         hosting::add_to_waitlist();|         ^^^^^^^ 使用了未声明的crate或模块`hosting`|
help: consider importing this module through its public re-export|
10 +     use crate::hosting;|warning: unused import: `crate::front_of_house::hosting`--> src/lib.rs:7:5|
7 | use crate::front_of_house::hosting;|     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|= note: `#[warn(unused_imports)]` 默认开启有关此错误的更多信息,请尝试运行 `rustc --explain E0433`。
warning: `restaurant` (lib) generated 1 warning
error: could not compile `restaurant` (lib) due to 1 previous error; 1 warning emitted

请注意,还有一条警告提示该 scope 内已不再使用该 import!要解决此问题,可以将 use 移动到 customer 模块内部,或者在子模块 customer 中通过 super::housing 引用父模块中的快捷方式。

创建惯用的 use 路径

在清单 7-11 中,你可能会想,为什么我们指定了 use crate::front_of_house::hosting,然后在 eat_at_restaurant 中调用 hosting::add_to_waitlist,而不是像清单 7-13 那样直接指定到函数 add_to_waitlist 的完整路径来达到同样的效果。

文件名:src/lib.rs

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

清单 7-13:使用 use 将函数 add_to_waitlist 引入作用域,这种写法不够惯用
虽然清单 7-11 和 7-13 都完成了相同的任务,但清单 7-11 是将函数通过 use 引入作用域的惯用方式。通过 use 引入父模块意味着调用该函数时必须指定父模块。这种调用方式明确表明该函数不是本地定义,同时又最大限度减少了完整路径的重复。相比之下,清单 7-13 的代码不太明确 add_to_waitlist 函数定义的位置。

另一方面,当引入结构体、枚举和其他项时,通过 use 指定完整路径是惯用做法。清单 7-14 展示了如何以惯用方式将标准库中的 HashMap 结构体引入二进制包(binary crate)的作用域。

文件名:src/main.rs

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

清单 7-14:以惯用方式将 HashMap 引入作用域
这种习惯没有特别强烈的理由,只是约定俗成,人们已经习惯这样读写 Rust 代码。

这个习惯唯一例外的是当我们需要通过多个 use 声明把两个同名项引入作用域时,因为 Rust 不允许这样做。清单 7-15 展示了如何把两个不同父模块但名称相同的 Result 类型引入,并且如何引用它们。

文件名:src/lib.rs

use std::fmt;
use std::io;fn function1() -> fmt::Result {// --省略--
}fn function2() -> io::Result<()> {// --省略--
}

清单 7-15:将两个同名类型带有其父模块一起引入相同作用域中
如你所见,通过使用父模块区分这两种 Result 类型。如果改为分别写成 use std::fmt::Resultuse std::io::Result,那么就会出现两个 Result 在相同作用域内冲突的问题,Rust 无法判断你指的是哪一个 Result。

使用 as 提供新名字

解决上述问题还有另一种方法,即在路径后面加上 as 并给类型起一个新的局部名字或别名。清单 7-16 演示了如何利用 as 重命名其中一个 Result 类型,从而实现与前面的代码等效功能。

文件名:src/lib.rs

use std::.fmt:Result;
use std::.io:Result as IoResult;fn function1() -> Result {// --省略--
}fn function2() -> IoResult<()> {// --省略--
}

清单 7–16: 使用 as 关键字重命名单个导入类型
第二条 use 声明中,我们选择给来自 std.io.Result 起新名字为 IoResult,这样不会与从 std.fmt.Result 导进来的 Result 冲突。无论是采用类似于 清单 7–15 或 清单 7–16 的写法,都被认为是符合规范(idiomatic)的,用哪个由你决定!

使用 pub use 重导出名称
当我们通过 use 把某个名称带进当前作用域时,该名称对外仍然是私有的。如果希望让外部代码也能像是在当前范围内一样访问该名称,可以结合 pub 和 use 一起使用。这称作“重导出”,即既把项目带进当前范围,也使得别人可以从这里再导出去使用它。

下面看一下修改后的版本,将根模块中的普通 use 改成 pub use:

文件名:src/lib.rs

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 ();
} 

清單7-17 : 用 pub use 讓名稱對任何代碼都可見並可從新範圍訪問
更改之前,如果外部代码要调用这个函数,需要走全路径,比如:
restaurant :: front_of_house :: hosting :: add_to _waitlist()
同时还要求 front_of_house 模块标记为 pub。
现在由于根模块里用了 pub use 来重新导出了 hosting 模块,
所以外部只需 restaurant :: hosting :: add_ to _ wait list ()
即可访问此功能。

重导出非常适合内部代码结构和用户视角不同的时候。例如餐厅比喻中,
餐厅管理者考虑“前台”和“后台”;
但是顾客通常不会这么思考餐厅各部分。
借助 pub use ,我们可以内部按一种结构组织代码,而向用户暴露另一套更合理、更易理解的接口。
这让库开发者和库用户都能受益。
关于 pub use 及其对文档影响,我们将在第十四章《Exporting a Convenient Public API with pub use》中详细介绍。

在第二章中使用外部包

我们编写了一个猜数字游戏项目,使用了一个名为 rand 的外部包来获取随机数。为了在项目中使用 rand,我们在 Cargo.toml 文件中添加了这一行:
文件名:Cargo.toml
rand = “0.8.5”

在 Cargo.toml 中将 rand 添加为依赖项,会告诉 Cargo 从 crates.io 下载 rand 包及其所有依赖,并使 rand 可用于我们的项目。

然后,为了将 rand 的定义引入到我们包的作用域内,我们添加了一条以 crate 名称 rand 开头的 use 语句,并列出了想要引入作用域的项。回想一下第二章“生成随机数”部分,我们将 Rng trait 引入作用域并调用了函数 rand::thread_rng:

use rand::Rng;fn main() {let secret_number = rand::thread_rng().gen_range(1..=100);
}

Rust 社区成员已经在 crates.io 上发布了许多包,将它们引入你的包也遵循相同步骤:先在你的包的 Cargo.toml 文件中列出它们,然后用 use 将这些 crate 中的项带入作用域。

注意,标准库 std 也是一个对我们包来说是外部的 crate。因为标准库随 Rust 语言一起发布,所以不需要修改 Cargo.toml 来包含 std。但我们仍然需要用 use 来引用它,从而把其中的项带进我们的代码作用域。例如,对于 HashMap,可以这样写:

use std::collections::HashMap;

这是一个以 std(标准库 crate 名称)开头的绝对路径。

使用嵌套路径简化大量 use 列表

如果从同一 crate 或模块中使用多个定义,逐条列出每个 item 会占用很多垂直空间。例如,在猜数字游戏中的 Listing 2-4 有两条从 std 引入内容的 use 声明:

文件名:src/main.rs

// --snip--
use std::cmp::Ordering;
use std::io;
// --snip--

相反,我们可以用嵌套路径一次性引入这些内容,只需指定公共部分路径后跟两个冒号,再用大括号括起不同部分,如 Listing 7-18 所示:

文件名:src/main.rs

// --snip--
use std::{cmp::Ordering, io};
// --snip--

Listing 7-18: 用嵌套路径一次性引入多个具有相同前缀的项

对于大型程序,从同一 crate 或模块通过嵌套路径导入大量项能显著减少单独 use 声明数量!

我们可以在任意层级使用嵌套路径,这对于合并共享子路径但又有差异部分的两条 use 非常有用。例如,Listing 7-19 展示两条声明,一条导入 std::io,另一条导入 std::io::Write

文件名:src/lib.rs

use std::io;
use std::io::Write;

Listing 7-19: 两个互为子路径关系的 use 声明

这两者共有公共部分是 std::io ,且第一行就是完整该公共部分。要合并成一行,可利用 nested path 中 self,如 Listing 7-20 所示:

文件名:src/lib.rs

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

Listing 7-20: 合并 Listing 7-19 路径的一行声明

此语句同时将 std::iostd.io.Write 带进当前作用域。

通配符操作符(Glob Operator)

若想把某一路径下所有公开定义都带进当前作用域,可以加上 * 通配符操作符,例如:

use std::collections::*;

这会把 std.collections 下所有公开元素全部导入当前范围。

请谨慎使用通配符!通配符可能让你难以判断哪些名称处于可见状态,以及程序里某名称具体来自哪里。

通配符通常用于测试时,把被测代码全部放进 tests 模块;第十一章“如何编写测试”会详细讲解。此外,它也偶尔作为预置模式(prelude pattern)的一部分出现——有关该模式更多信息,请参阅标准库文档。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/91131.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/91131.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/91131.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

7.Linux :进程管理,进程控制与计划任务

Linux &#xff1a;进程管理&#xff0c;进程控制与计划任务 一、进程管理 1. 进程与程序 程序&#xff1a;静态的可执行文件&#xff08;存储于磁盘&#xff09;。进程&#xff1a;动态执行的程序实例&#xff08;占用CPU/内存&#xff09;。 2. 查看进程命令作用常用组合ps静…

Matplotlib(四)- 图表样式美化

文章目录一、Matplotlib图表样式介绍1. 图表样式简介2. 默认图表样式2.1 查看默认配置2.2 常用的配置3. 图表样式修改3.1 局部修改3.1.1 通过绘图方法设置参数修改3.1.2 通过rcParams修改3.1.3 通过rc()方法修改3.2 全局修改二、颜色设置1. 颜色的三种表示方式1.1 颜色单词1.2 …

三十四、【Linux常用工具】rsync+inotify实时同步演示

实时同步演示技术架构全景核心组件详解1. inotify 内核子系统2. Rsync 高效同步工具实践演示一、环境准备与安装1. 检查内核支持2. 安装 inotify-tools二、配置 Rsync 服务端&#xff08;目标机&#xff09;1. 创建 Rsync 配置文件2. 启动 Rsync 守护进程三、配置实时同步脚本&…

windows环境下MySQL 8.0 修改或重置密码

windows环境下MySQL 8.0 修改或重置密码 1打开命令窗口cmd&#xff0c;输入命令&#xff1a;net stop mysql&#xff0c; 停止MySQL服务&#xff0c; 开启跳过密码验证登录的MySQL服务 2输入命令 mysqld --console --skip-grant-tables --shared-memory 再打开一个新的cmd&…

基于YOLOP与GAN的图像修复与防御系统设计与实现

基于YOLOP与GAN的图像修复与防御系统设计与实现 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff0c;觉得好请收藏。点击跳转到网站。 1. 引言 1.1 研究背景 随着深度学习技术在计算机视觉领域的…

将目录文件转移到D盘,使之后的下载缓存数据转移,不再存入c盘

将 C:\Users 文件夹&#xff08;用户文件夹&#xff09;转移到其他盘是一个复杂且风险较高的操作。C:\Users 文件夹包含了系统中每个用户的个人数据和配置文件&#xff0c;修改这个路径可能会导致系统出现问题&#xff0c;包括程序无法正常工作或无法登录。因此&#xff0c; 强…

Cesium大气散射效果

由于做全球体积云效果的需要&#xff0c;再来研究下大气散射效果和体积云类似&#xff0c;关于大气散射颜色计算的过程也仅发生在这两个球体之间。如图所示。计算从相机出发的视线与球壳的交点&#xff0c;如果不相交&#xff0c;则该视线方向上不会发生大气散射&#xff0c;直…

预过滤环境光贴图制作教程:第二步 - 生成环境贴图图集

核心目标 本步骤的核心是生成一张包含 6 级分辨率的环境贴图图集(envAtlas),实现: 将第一步的立方体贴图(sourceCube)重新映射为等矩形投影(适合存储和采样); 生成 6 级不同分辨率的等矩形数据(0 级最高清,5 级最模糊); 用 RGBP 编码压缩 HDR 数据(平衡精度与存…

1. ESP开发之实体按键(KEYPADBUTTON)控制LVGL控件

说明LV_INDEV_TYPE_BUTTON的使用LV_INDEV_TYPE_KEYPAD的使用 说明 本实验使用LVGL版本为v9.2 LVGL中有四种输入设备,如下LV_INDEV_TYPE_POINTER, /**< Touch pad, mouse, external button*/ LV_INDEV_TYPE_KEYPAD, /**< Keypad or keyboard*/ LV_INDEV_TYPE_BUTTON, /*…

C++:STL中list的使用和模拟实现

C中的list是标准模板库&#xff08;STL&#xff09;提供的双向链表容器&#xff0c;支持高效的元素插入和删除操作。在上一篇中讲解了vector的使用和模拟实现&#xff0c;vector是具有连续的空间&#xff0c;迭代器是可以随机的&#xff0c;而list却于vector不同&#xff0c;li…

【编号58-61】我国四大高原矢量示意图shp数据

今天分享的是&#xff1a;中国四大高原&#xff0c;分别是青藏高原、内蒙古高原、黄土高原、云贵高原。青藏高原位置与范围&#xff1a;位于中国西南部&#xff0c;包括西藏、青海的全部&#xff0c;川西高原及滇西北高原等部分地区。它的边界&#xff0c;向东是横断山脉&#…

【AI落地应用实战】利用 Amazon Bedrock Claude3 打造个性化 AI Character 应用

目录一、引言&#xff1a;AI Character应用的市场前景与技术基础二、技术架构设计2.1、整体方案概述2.2、核心组件介绍2.3、部署架构图三、系统部署方案3.1、方案总述3.2、实践流程1️⃣. Bedrock 配置2️⃣. 安装 SillyTavern3️⃣. 配置 SillyTavern 使用 Claude3 模型4️⃣.…

Java常用日志框架介绍

Java提供了很多第三方的日志框架可供使用&#xff0c;按照现在的设计理念&#xff0c;一般把日志框架分成门面(Facade)部分和具体实现(Implementation)部分&#xff0c;门面(Facade)提供了抽象的api规范&#xff0c;实现(Implementation)负责实现api完成具体的日志记录功能。开…

飞书 —— 多维表格 —— AI生成

1.添加关联账号&#xff1a; 2.获取密钥 ARK_API_KEY 进入火山引擎服务页面&#xff1a;https://console.volcengine.com/ark/region:arkcn-beijing/model/detail?Iddeepseek-r1 先进入推理模型 > 快捷API接入 再去在线推理中创建推理接入点 点击新创建好的接入点的API调…

我的世界模组开发教程——资源(1)

下面我们来研究一下ResourceLocation,每次开启游戏时都会报这个错误:“ResourceLocation 中的 ResourceLocation(String) 已过时, 且标记为待删除”,下面我们来详细的研究一下这个类 ResourceLocation ResourceLocation 是 Minecraft 中用于唯一标识游戏资源的核心类(如方…

我从 Web2 转型到 Web3 的 9 条经验总结

作者&#xff1a;Forte Group 高级区块链工程师 Yurii Kovalchuk原文&#xff1a;https://cryptoslate.com/why-i-left-web2-for-web3-and-why-you-might-too/三年前&#xff0c;我做出了一个彻底改变职业轨迹的决定&#xff1a;离开熟悉的 Web2&#xff0c;投身于深邃、混乱却…

【MySQL 数据库】MySQL索引特性(一)磁盘存储定位扇区InnoDB页

文章目录没有索引&#xff0c;可能会有什么问题二、认识磁盘2.1 MySQL与存储2.2 磁盘&#xff1a;2.3 扇区2.4 定位扇区2.5 结论三、三者作用流程&#xff08;磁盘&#xff0c;块&#xff0c;InnoDB页&#xff09;四、MySQL与磁盘交互基本单位五、建立共识&#x1f6a9;总结没有…

2419. 按位与最大的最长子数组

Problem: 2419. 按位与最大的最长子数组 文章目录思路解题过程复杂度Code思路 按位异或只会让数值越来越小&#xff0c;因此最长的连续按位与的最大值只存在于连续最大值中。 解题过程 遍历数组取出最大值&#xff0c;再遍历找到每一次连续最大值&#xff0c;从中取出最长的连续…

基于Java(SpringBoot)+Vue+MySQL 实现(Web)的网络课程平台

基于 SpringBoot 的网络课程平台1 绪论1.1 引言本科题研究并实现了一个面向网络学习的平台&#xff0c;为需要学习的人提供了一个学习的平台。任何人都课在本平台进行注册登录&#xff0c;学习观看视频。本平台是一个关于网络课程学习平台&#xff0c;学员科自主选择视频学习&a…

Centos7 | 防火墙(firewalld)使用ipset管理ip地址的集合

文章目录一、firewalld中ipset的用途1.1 用途1.2 注意与iptables所用的ipset命令的不同&#xff0c;1.3 配置详解二、firewalld中ipset的操作例子2.1 新建一个set2.2 在set中添加ip2.3 从set中删除ip2.4 删除一个set2.5 打印一个set的文件路径2.6 打印一个set的内容2.8 判断一个…