Rust隐私规则:如何将结构体移入模块且仅对原模块可见
Rust模块拆分后的可见性控制方案
用精准的可见性修饰符替代全局pub
Rust提供了比单纯pub更灵活的访问控制,既能让父模块访问子模块里的结构体,又能对外隐藏细节,完美适配你拆分长文件的需求。
1. 只让直接父模块访问:pub(super)
如果你的需求仅仅是父模块能访问,其他模块一概不行,给结构体和需要调用的方法加上pub(super)修饰:
// 子模块文件:src/child.rs pub(super) struct MyStruct { data: i32, } impl MyStruct { pub(super) fn new(data: i32) -> Self { MyStruct { data } } // 父模块要调用的方法也得加pub(super) pub(super) fn get_data(&self) -> i32 { self.data } }
然后在父模块里直接用就行:
// 父模块文件:src/lib.rs 或 src/main.rs mod child; use child::MyStruct; fn main() { let s = MyStruct::new(42); println!("{}", s.get_data()); }
这种设置下,除了这个直接父模块,哪怕是同一crate里的其他子模块也碰不到MyStruct,彻底保证封装性。
2. 让整个crate内部都能访问:pub(crate)
如果拆分的多个子模块之间也需要互相访问,但不想对外暴露,就用pub(crate):
// 子模块文件:src/child.rs pub(crate) struct MyStruct { data: i32, } impl MyStruct { pub(crate) fn new(data: i32) -> Self { MyStruct { data } } }
这样整个项目(crate)里的任何模块都能导入使用MyStruct,但当别人把你的crate当依赖用的时候,完全看不到这个结构体。
3. 多子模块的组织技巧:用父模块封装内部细节
如果有一堆相关的子模块需要互相调用,但对外只暴露统一接口,可以把它们都塞进一个私有父模块里:
// src/lib.rs // 这个父模块默认私有,对外不可见 mod internal { pub mod module_a { pub(super) struct StructA; } pub mod module_b { use super::module_a::StructA; pub fn do_something() { let _a = StructA; // 这里可以随便用StructA } } } // 对外只暴露需要的公开接口 pub fn public_entry() { internal::module_b::do_something(); }
这种方式下,所有内部结构体都只在internal范围内可见,对外完全隐藏,同时代码拆分得清清楚楚。
总结一下
- 别用全局
pub,优先选pub(super)或pub(crate)控制访问范围 - 拆分模块时,内部细节尽量私有,只对外暴露必要的API
- Rust的可见性是按作用域来的,精准控制既能拆分代码,又不破坏封装
内容的提问来源于stack exchange,提问作者user2138149
相关产品推荐
相关产品推荐

