我有一个箱子,里面有很多代码,所以我把它分成了多个文件/模块.然而,有些模块有内部不安全的东西(例如原始指针),我需要向不同的模块公开这些东西,但我不想向我的 crate 的用户公开.我该怎么做?

我能想到的唯一方法就是把我的 crate 变成一个大模块,但是除了this solution个文件之外,没有办法把它分割成不同的文件,seems个文件有点粗糙.

通常,当我遇到一个现实世界中的问题,Rust文档中的简单示例无法充分解释时,我只是复制一个流行的现实世界 crate ,例如git2-rs,但这似乎有效地公开了一切,包括原始指针.

推荐答案

为了从图书馆 crate 中导出item,必须至少有一条通向它的路径,其中every组件是公共的.这意味着,你只需要将一个物品在你的 crate 中公开,而不是从 crate 中导出(从现在起,为了模仿C#术语,我将其称为"内部")就可以将其放在 crate 根目录下的一个私有模块中.

然而,这种解决方案是相当有限的.如果你想要一个包含导出函数和and个内部函数的模块呢?为了导出一些函数,我们需要将模块公开,这意味着该模块中的所有公共项也将被导出.

Rust 1.18年以来,有一种解决方案适应了这种情况:pub(restricted)年.此功能允许您指定项目的"公开程度".语法非常灵活(您可以使一个项目对特定的模块树而不是整个 crate 可见),但如果您想保持简单,pub(crate)将使一个项目在 crate 中的任何位置都可以访问,但对其他 crate 不可以访问(相当于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的情况.例如,如何使导出的 struct 的某些字段可以在同一 crate 中的其他模块中访问,而不必同时导出它们?唯一的 Select 是公开一个带有单个私有字段的包装器,其类型是具有公共字段的 struct ;如果您想对其他 crate 隐藏所有字段,那么这很好,但如果您想在同一个 struct 中公开一些字段,使其他一些字段成为内部字段,那么这就不行了.

Rust相关问答推荐

rust 蚀将动力特性浇到混凝土 struct 上是行不通的

关联类型(类型参数)命名约定

在特征中使用Async时,如何解决不透明类型`impl Future<;out=self>;`不满足其关联的类型边界和警告?

有没有办法避免在While循环中多次borrow `*分支`

函数内模块的父作用域的访问类型

我可以在不收集或克隆的情况下,将一个带有Item=(key,val)的迭代器拆分成单独的key iter和val iter吗?

如果变量本身不是None,如何返回;如果没有,则返回None&Quot;?

为什么&;mut buf[0..buf.len()]会触发一个可变/不可变的borrow 错误?

Rust从关联函数启动线程

如何设置activx websocket actorless的消息大小限制?

在 Rust 中,是否可以定义一个需要实现类型的构造函数的对象安全特征?

如何正确使用git2::Remote::push?

在1.5n次比较中找到整数向量中的最大和次大整数

trait 对象指针的生命周期

如何在 Rust 中将 bson::Bson 转换为 Vec

无法理解 Rust 对临时值的不可变和可变引用是如何被删除的

为什么 Rust 允许写入不可变的 RwLock?

TcpStream::connect - 匹配武器具有不兼容的类型

如何从 Rust 中不同类型的多个部分加入 Path?

为什么 u64::trailing_zeros() 在无分支工作时生成分支程序集?