Rust
的代码从逻辑上是分crate
和mod
管理的。所谓crate
大家可以理解为“项 目”。
每个crate
是一个完整的编译单元,它可以生成为一个lib
或者exe
可执行文件。
而在crate
内部,则是由mod
这个概念管理的,所谓mod
大家可以理解为namespace
。
我们可以使用use
语句把其他模块中的内容引入到当前模块中来。关于Rust
模块系统 的详细说明,可参见本书第五部分。
Rust
有一个极简标准库,叫作std
,除了极少数嵌入式系统下无法使用标准库之 外,绝大部分情况下,我们都需要用到标准库里面的东西。为了给大家减少麻烦, Rust编译器对标准库有特殊处理。默认情况下,用户不需要手动添加对标准库的依 赖,编译器会自动引入对标准库的依赖。除此之外,标准库中的某些type、trait、 function、macro
等实在是太常用了。
每次都写use
语句确实非常无聊,因此标准库提 供了一个std::prelude
模块,在这个模块中导出了一些最常见的类型、trait
等东 西,编译器会为用户写的每个crate自动插入一句话:
use std::prelude::*;
这样,标准库里面的这些最重要的类型、trait
等名字就可以直接使用,而无须 每次都写全称或者use语句。
Prelude
模块的源码在src/libstd/prelude/
文件夹下。我们可以看到,目前的mod.rs
中,直接导出了v1模块中的内容,而v1.rs中,则是编译器为我们自动导入的相关 trait
和类型。
Format格式详细说明
在后面的内容中,我们还会大量使用println!
宏,因此提前介绍一下这个宏的
基本用法。跟C语言的printf函数类似,这个宏也支持各种格式控制,示例如下:
fn main() {
println!("{}", 1);
println!("{:o}", 9);
println!("{:x}", 255);
println!("{:X}", 255);
println!("{:p}", &0);
println!("{:b}", 15);
println!("{:e}", 10000f32);
println!("{:E}", 10000f32);
// 默认用法,打印Display // 八进制
// 十六进制 小写
// 十六进制 大写
// 指针
// 二进制
// 科学计数(小写) // 科学计数(大写)
// 打印Debug println!("{a} {b} {b}", a = "x", b = "y"); // 命名参数
}
Rust
中还有一系列的宏,都是用的同样的格式控制规则,如format!write! writeln!等。
详细文档可以参见标准库文档中std::fmt模块中的说明。
Rust
标准库中之所以设计了这么一个宏来做标准输出,主要是为了更好地错误 检查。大家可以试试,如果出现参数个数、格式等各种原因不匹配会直接导致编译 错误。而函数则不具备字符串格式化的静态检查功能,如果出现了不匹配的情况, 只能是运行期错误。这个宏最终还是调用了std::io模块内提供的一些函数来完成 的。
如果用户需要更精细地控制标准输出操作,也可以直接调用标准库来完成。