为了从库 crate 中导出 item,必须至少有一个路径通向它,其中 每个 组件都是公共的。这意味着您需要在您的 crate 中公开一个项目但不从 crate 中导出(我从现在开始将其称为“内部”,以模仿 C# 术语)是将它放在 crate 根目录下的私有模块中.
但是,该解决方案具有很大的限制性。如果您想要一个具有导出函数和内部函数的模块怎么办?为了导出某些功能,我们需要将模块设为公共,这意味着该模块中的所有公共项也会被导出。
自从Rust 1.18,就有了适应这种场景的解决方案:pub(restricted)。此功能可让您指定项目的“公开程度”。语法非常灵活(您可以使项目对特定模块树而不是整个 crate 可见),但如果您想保持简单,pub(crate) 将使项目在 crate 中的任何位置都可以访问,但不能被其他人访问crates(相当于 C# 中的 internal)。
例如,假设我们想要一个模块util,其中导出foo(如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 中隐藏所有字段,则效果很好,但如果您想公开某些字段并在同一结构中创建一些其他字段,则不行。