我有一个包含大量代码的包,所以我将它分成多个文件/模块.但是,有些模块有内部不安全的东西(例如原始指针),我需要向不同的模块公开,但我不想向我的箱子的用户公开.我怎样才能做到这一点?
我能想到的唯一方法就是让我的箱子只是一个大模块,但是除了这个似乎有点hacky的解决方案之外,没有办法将它分成不同的文件.
通常当我遇到一个现实世界的问题时,Rust文档中的简单示例没有充分解释我只是复制一个流行的真实世界的箱子,例如git2-rs,但这似乎只是有效地使一切都公开,包括原始指针.
为了从库包中导出项目,必须至少有一个通向它的路径,其中每个组件都是公共的.这意味着你需要在你的箱子里公开一件物品而不是从箱子里出来的所有东西(我从现在开始称之为"内部",模仿C#术语)就是把它放在箱子根下的私人模块中.
但是,该解决方案非常严格.如果您想要一个具有导出功能和内部功能的模块,该怎么办?为了导出一些函数,我们需要公开模块,这意味着该模块中的所有公共项目也将被导出.
自Rust 1.18以来,有一种适用于这种情况的解决方案:pub(restricted)
.此功能允许您指定项目应该"公开".语法非常灵活(你可以让一个项目对特定的模块树而不是整个箱子都可见),但是如果你想保持简单,pub(crate)
就可以在箱子里的任何地方访问一个项目,而不是其他的箱子(等价物)到internal
在C#).
例如,假设我们想要一个导出(as )的模块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
在仅包含reexport的公共模块中公开(with )的项目.以下是上面的示例:
pub mod util { pub use util_impl::foo; } mod util_impl { pub fn foo() { unimplemented!() } pub fn bar() { unimplemented!() } fn baz() { unimplemented!() } }
这不仅不易阅读和理解,而且不包括pub
可以使用的所有情况.例如,如何在同一个包中的其他模块中访问导出结构的某些字段而不导出它们?唯一的选择是公开一个包含一个私有字段的包装器,其类型是具有公共字段的结构; 如果要隐藏其他包中的所有字段,则可以正常工作,但如果要在同一结构中显示某些字段并将其他字段设置为内部,则无效.