资源系统

Mingling 如何管理全局状态

命令行程序经常需要共享一些全局的东西——配置文件、数据库连接、计数器、当前工作目录。 在普通 Rust 里你可能会用 `OnceCell` 或 `lazy_static`,在 Mingling 里有一套统一的机制:**资源系统**。 ## 什么是资源? 资源就是在多个 Chain 和 Renderer 之间共享的数据。 你只需要定义一个类型、注册到 Program,然后在函数签名里声明你需要它——剩下的注入和生命周期管理都由框架完成。 ## 核心机制:ResourceMarker 任何同时实现了 `Default + Clone` 的类型都可以自动成为资源。框架会为它实现 `ResourceMarker` trait,使其具备: - **`res_clone()`** —— 当多个 Chain 同时访问时,框架可以通过 clone 来避免锁竞争 - **`res_default()`** —— 资源未注册时提供兜底值 如果你需要更精细的生命周期控制,可以使用 `LazyRes`。它允许资源在第一次被访问时才初始化,并且可以在析构时执行回调(比如退出前保存状态到磁盘)。 ## 为什么不用全局变量? 传统做法的静态变量是隐式依赖 —— 你看函数签名根本不知道它用了什么全局状态。而 Mingling 的资源注入让 **依赖显式化**: - 函数需要什么资源,参数列表就写什么 - `&T` 表示只读访问,`&mut T` 表示可修改 - 调用者一眼就能看出这个函数的副作用 例如: ```rust @@@ use mingling::res::ResExitCode; @@@ pack!(ErrorFileNotFound = ()); #[chain] fn handle_error_file_not_found( error: ErrorFileNotFound, ec: &mut ResExitCode // 通过签名可以看出副作用! ) { ec.exit_code = 2; // 这里修改了退出码 } ``` ## 资源与 Setup 的关系 资源通常通过两个途径注册到 Program: 1. **直接注册** —— 在 `main` 中调用 `program.with_resource(...)` 2. **通过 Setup** —— 使用 `DirectoryEnvironmentSetup` 等内置 Setup 批量注册(如 `ResCurrentDir`、`ResHomeDir`) Setup 是比资源更高层的抽象,一个 Setup 可以注册多个资源并做其他初始化工作。 详见教程中的 [程序装配](./pages/8-setup-and-resources) 一章。

Written by @Weicao-CatilGrass