如果从模块导出的项暴露它们,如何组织内部代码?



我正在做一个Rust模块,它有一个很小的外部接口,但是它的内部实现是大而复杂的。

是否有一个合理的方法来避免有一个巨大的文件与所有的模块代码,同时仍然暴露一个小的接口给外部模块消费者?

老实说,Rust不允许你在同一个模块中使用多个文件,就像Go允许包目录一样。Rust模块是否定义在目录中并不重要,它仍然需要一个单独的文件。

这样,为了拆分代码,你就不得不使用子模块来处理你想要拆分的子类型或实现细节。我理解这对于编译后的代码来说应该无关紧要,因为模块组织的所有开销都被删除了。

但是有一个设计问题,如果我把东西分成模块,那些需要导出的东西,这样我就可以从我的其他模块中使用它们…但是那些"出口的内部"也可以被外部消费者使用,对吗?有没有一种方法可以避免暴露这些内部接口?

但是有一个设计问题,如果我把东西分成模块,那些需要导出的东西,这样我就可以从我的其他模块中使用它们…但是那些"出口的内部"也可以被外部消费者使用,对吗?

不,他们不能。

在子模块中将一个符号设为public,只会使它对它的直接父模块可用。然后,父模块必须通过pub use重新导出该符号,以使可见性"冒出"。

mod foo {
mod bar {
pub fn visible_in_foo() {}
pub fn visible_in_root() {}
fn private() {}
}

// Re-export to make visible at the next outer level
pub use bar::visible_in_root;
pub fn foo() {
// We are in the immediate parent, so both `pub` functions are visible
bar::visible_in_foo();
bar::visible_in_root();
// bar::private(); - Won't compile
}
}
// Make it public to consumers of the library, aka. external API
pub use foo::foo;
fn main() {
// Notice that it's just `foo`. Not `foo::bar` or `bar`.
// Re-exporting makes the symbol a part of module `foo`.
foo::visible_in_root();
// foo::visible_in_foo(); - Won't compile
// `foo::foo` does have access to the inner module, though,
// so we can call `foo::bar::visible_in_foo` indirectly here.
foo::foo();
}

另外,你可以将符号标记为pub(crate),它的工作原理类似于pub,除了它阻止符号在crate之外成为公共的,即使它被所有的父模块重新导出。

进一步阅读:

  • Rust编程语言-定义模块来控制作用域和隐私
  • Rust参考-可见性和隐私

最新更新