rust 如果从模块导出的项公开了内部代码,如何组织它们?

bcs8qyzn  于 2023-01-13  发布在  其他
关注(0)|答案(1)|浏览(129)

我正在开发一个Rust模块,它有一个很小的外部接口,但是它的内部实现又大又复杂。
有没有一种明智的方法可以避免拥有一个包含模块所有代码的巨大文件,同时仍然向外部模块使用者公开一个小接口?
AFAIK,Rust不允许在同一个模块中使用多个文件,比如Go语言允许使用包目录。Rust模块定义在一个目录中并不重要,它仍然需要一个单独的文件。
这样,为了分割代码,你不得不使用子模块来表示你想要分割的子类型或实现细节。我理解这对编译代码来说应该没有多大关系,模块组织的所有开销都被移除了。
但是有一个设计问题,如果我把东西分成模块,这些模块就需要导出东西,这样我就可以从其他模块中使用它们......但是那些“导出的内部组件”也可以被外部消费者使用,对吗?有没有办法避免暴露那些内部接口?

xu3bshqb

xu3bshqb1#

但是有一个设计问题,如果我把东西分成模块,这些模块将需要导出东西,以便我可以从其他模块中使用它们...但是这些"导出的内部组件"也可以由外部消费者使用,对吗?
不,他们不能。
在子模块中公开一个符号只会使它对它的直接父模块可用,然后父模块必须通过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,只是它可以防止符号在机箱外公开,即使它被其所有父模块重新导出。
进一步阅读:

相关问题