包管理(Cargo)
cargo 命令创建包
cargo new xxx --lib
创建一个名为xxx的包;cargo new xxx
或者 cargo new xxx --bin
创建一个名为xxx的可被编译为可执行文件的包。
使用第三方包
- 在
Cargo.toml
中的[dependencies]
下加入包的依赖; - 在需要引入的文件头部加入
extern crate
包名; 之后才可以use
包(Rust 2015
)。在2018
中,直接可以用use xxx
。
Note:Cargo
默认把连字符替换为下划线。
Cargo文件格式
[package]表配置
描述的都是与包相关的元数据,比如包名,作者等。数组使用[],多段文字使用”””。
build = "buidl.rs"
指定构建脚本; workspace = ".."
指定工作空间为父目录。
[badges]表配置
云端的持续集成服务。
[workspace]表配置
members = ["bench", "regex-capi"]
指定子包。
[dependencies]表配置
配置依赖文件。
[features]表配置
条件编译功能相关。在代码中对应#[cfg(featrue = "xxx")]
。
[lib]表配置
表示最终编译目标库的信息:name,crate-type, path, test, bench等。
[ [test] ]表配置
用两个中括号,表示数组。
[profile]表配置
自定义rustc编译配置。
模块系统
如果存在与文件名同名的目录,则该目录下的模块都是该文件的子模块。
read_func.rs
1 | pub mod static_kv; //pub关键字使得可以在main.rs中:use read_func::static_kv |
Rust会通过mod
关键字去当前模块的子模块中寻找static_kv
模块。模块名字可以被以下表述:1.模块名.rs;2.与模块名相同的文件夹,并且该文件夹包含mod.rs
。
read_func/static_kv.rs
1 | use lazy_static::lazy_static; |
main.rs
1 | mod read_func; |
第一行mod引入模块。
第二行的crate
可以用self
代替,代表当前的crate
,以main.rs
为起点寻找当前相对路径下的read_func
模块。如果是第三方包,就不需要写crate
前缀。
模块间的关系
模块嵌套
1 | mod sound { |
树形结构:
1 | crate |
私有性规则有如下:
- 所有项(函数、方法、结构体、枚举、模块和常量)默认是私有的。
- 可以使用 pub 关键字使项变为公有。
- 不允许使用定义于当前模块的子模块中的私有代码。
- 允许使用任何定义于父模块或当前模块中的代码。
1 | mod sound { |
也可以使用 super 开头来构建相对路径。这么做类似于文件系统中以 .. 开头:该路径从 父 模块开始而不是当前模块。
1 | mod instrument { |
clarinet
函数位于instrument
模块中,所以可以使用 super
进入 instrument
的父模块,也就是根 crate
。从这里可以找到 breathe_in
。使用super
相对路径可以方便的进行扩展,而不用更改路径来调用。
sound
模块放入sound.rs
文件中,调用方式不变。
重新导出
1 | pub use crate::sound::instrument; |
可以简化外部调用的导出路径(外部调用:use xxx::instrument;
),也不需要对外暴露模块(sound
)。
一般重新导出放在lib.rs
中。main.rs
结合lib.rs
的形式,是二进制包的最佳实践。
可见性
1 | pub mod outer_mod { |
关于pub:
- 如果不显示使用pub,则函数或者模块可见性默认为私有的;
- pub,可以对外暴露公共接口;
- pub(crate),对整个crate可见;
- pub(in Path),其中Path是模块路径,表示可以通过此Path路径来限定可见范围;
- pub(self) / pub(in self),只限当前模块可见;
- pub(super) / pub(in super),当前模块和父模块中可见。
Note:trait中关联类型和Enum中变体的可见性,会随着trait和Enum的可见性而变化。但是结构体中的字段需要单独使用pub来改变可见性。