为了从库 crate 中导出项目,必须至少有一个通向它的路径,其中每个组件都是公共的。这意味着你需要在你的 crate 中公开一个项目而不是从 crate 中导出(从现在开始我称之为“内部”,以模仿 C# 术语)就是将它放在 crate 根目录下的私有模块中.
但是,该解决方案具有很大的限制性。如果您想要一个具有导出函数和内部函数的模块怎么办?为了导出某些功能,我们需要将模块设为公共,这意味着该模块中的所有公共项也将被导出。
从Rust 1.18开始,有一个适合这种场景的解决方案:pub(restricted)
. 此功能可让您指定项目的“公开程度”。语法非常灵活(您可以使项目对特定模块树而不是整个 crate 可见),但如果您想保持简单,pub(crate)
将使项目在 crate 中的任何位置都可访问,但对其他 crate 不可用(等效在internal
C# 中)。
例如,假设我们想要一个模块util
,其中foo
导出(as mycrate::util::foo
),bar
是内部的并且baz
是模块私有的。代码可能如下所示:
pub mod util {
pub fn foo() {
unimplemented!()
}
pub(crate) fn bar() {
unimplemented!()
}
fn baz() {
unimplemented!()
}
}
如果你被 1.18 之前的 Rust 卡住了,有一个解决方法,但它有点笨拙。它涉及在私有模块中定义所有项目,并仅在仅包含重新导出的公共模块中重新导出您想要公开(使用pub use
)的项目。上面的示例如下所示:
pub mod util {
pub use util_impl::foo;
}
mod util_impl {
pub fn foo() {
unimplemented!()
}
pub fn bar() {
unimplemented!()
}
fn baz() {
unimplemented!()
}
}
这不仅不容易阅读和理解,而且没有涵盖所有pub
可以使用的情况。例如,如何使导出结构的某些字段在同一个 crate 中的其他模块中可访问,而不导出它们?唯一的选择是公开一个带有单个私有字段的包装器,其类型是具有公共字段的结构;如果您想从其他 crate 中隐藏所有字段,那效果很好,但如果您想公开一些字段并在同一个结构中创建一些其他字段,则不行。