简体   繁体   English

Rust有什么办法组织内码?

[英]Any way to organize internal code in Rust?

I am working on a Rust module that has a small external interface, but its internal implementation is large and complex.我正在开发一个 Rust 模块,它有一个小的外部接口,但它的内部实现又大又复杂。

Is there a sane way to avoid having a huge file with all the code for the module while still exposing a small interface to external module consumers?有没有一种明智的方法可以避免拥有一个包含模块所有代码的巨大文件,同时仍然向外部模块使用者公开一个小接口?

AFAIK, Rust does not allow you to use several files for the same module, as for instance Go allows for package directories. AFAIK,Rust 不允许您为同一模块使用多个文件,例如 Go 允许 package 目录。 It does not matter that the Rust module is defined in a directory, it still expects one single file. Rust 模块定义在一个目录中并不重要,它仍然需要一个文件。

That way, to split code up you are forced to use sub-modules for sub-types or implementation details that you would want to split apart.这样,为了拆分代码,您不得不使用子模块来处理您想要拆分的子类型或实现细节。 I understand that should not matter much for compiled code, all overhead of the module organization is removed.我知道对于编译后的代码来说应该无关紧要,模块组织的所有开销都被删除了。

But there is a design problem, if I split things up in modules, those will need to export things so that I can used them from my other modules... but then those "exported internals" can ALSO be used by external consumers, right?但是有一个设计问题,如果我把东西分成模块,那些将需要导出东西,以便我可以从我的其他模块使用它们......但是那些“导出的内部”也可以被外部消费者使用,对吧? Is there a way to avoid exposing those internal interfaces?有没有办法避免暴露那些内部接口?

But there is a design problem, if I split things up in modules, those will need to export things so that I can used them from my other modules... but then those "exported internals" can ALSO be used by external consumers, right?但是有一个设计问题,如果我把东西分成模块,那些将需要导出东西,以便我可以从我的其他模块使用它们......但是那些“导出的内部”也可以被外部消费者使用,对吧?

No, they can not.不,他们不能。

Making a symbol public in a sub-module only makes it available to its immediate parent.在子模块中公开符号只会使其对其直接父级可用。 That parent module would then have to re-export that symbol via pub use for the visibility to "bubble up".然后,该父模块必须通过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();
}

Additionally, you can mark symbols as pub(crate) , which works like pub , except it prevents the symbol from becoming public outside the crate, even if it were re-exported by all of its parent modules.此外,您可以将符号标记为pub(crate) ,其工作方式与pub类似,只是它可以防止符号在 crate 之外公开,即使它已被其所有父模块重新导出。

Further reading:延伸阅读:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM