Sway 语言 `[storage]` 属性:函数读写状态存储的纯度声明实战指南

发布时间:2026/9/12 17:36:40
Sway 语言 `[storage]` 属性:函数读写状态存储的纯度声明实战指南 Sway 语言#[storage]属性函数读写状态存储的纯度声明实战指南【免费下载链接】sway Empowering everyone to build reliable and efficient smart contracts.项目地址: https://gitcode.com/GitHub_Trending/sw/sway#[storage]是 Sway 语言中用于标注函数存储纯度purity的核心属性它明确告知编译器一个函数是否从链上 storage 读取、写入或完全保持纯净pure。本指南以 storage.md 为骨架结合 Sway 仓库中的 标注代码示例、storage 操作文档 与sway-lib-std标准库源码系统讲解该属性的三种取值read、write、read, write、语法位置、配合storage块的完整读写实战以及底层实现机制帮助你写出编译通过、语义准确的链上合约函数。什么是#[storage]属性定义函数对存储的纯度在 Fuel 区块链上智能合约 可以在交易之间持久化地存储与操作数据这一持久化区域在 Sway 中称为storage。而#[storage]属性attribute就是用来描述一个函数对 storage 的纯度purity即该函数是否会与链上存储发生交互。根据 storage.md 文档 的定义该属性表达了四种状态纯度状态属性标注含义只读#[storage(read)]函数从 storage 读取数据只写#[storage(write)]函数向 storage 写入数据读写#[storage(read, write)]函数既读又写 storage纯净省略标注既不读也不写 storage关键规则是当函数完全纯净时不写任何标注否则必须在函数签名上方放置正确的标注。在 Sway 中attribute 本质是一种元数据metadata为声明提供附加功能见 attributes/index.md而#[storage]则是其中与链上状态交互强相关的一类。为什么需要声明纯度从 Sway 编译器与运行时设计看声明纯度有两大作用语义正确性函数体内的storage访问必须与标注一致。若在标注了#[storage(read)]的函数中写入 storage或是在无标注的纯净函数中访问 storage编译器会报错从而在编译期拦截存储读写歧义。可读性与审计性调用者仅凭函数签名即可判断一个方法是否会改变链上状态这对于判断合约行为例如是否会消耗 Gas 写存储非常直观。语法与位置标注放在函数签名上方#[storage(...)]以属性形式书写在函数签名fn之前的正上方。属性参数写在圆括号内多个参数用英文逗号分隔。仓库中的 code/language/annotations/src/main.sw 展示了三种标注在真实合约中的完整用法。该文件开头的storage块为后续函数提供了被读写的数据源contract; storage { my_storage_namespace { var: u64 0, } }这里的my_storage_namespace是 Sway 的 storage 命名空间其中的var是一个u64类型的存储变量默认值0。注意在 Sway 中访问存储变量必须显式使用storage::前缀命名空间访问或storage.前缀顶层访问以区分局部变量与存储变量详见 read-write.md。三种标注详解与完整代码示例以下三个小节分别对应文档中定义的三种非纯净状态代码均来自仓库中的 main.sw。只读#[storage(read)]当函数只从 storage 读取数据、不修改任何存储时使用read关键字#[storage(read)] fn read() { let variable storage::my_storage_namespace.var.read(); }对应 operations 文档 中的说明对于内置类型可以直接调用read()方法从存储中取出值。示例中storage::my_storage_namespace.var.read()的调用链是以storage::定位到my_storage_namespace命名空间 → 选择其中的var变量 → 调用其read()方法取回u64值。只写#[storage(write)]当函数只向 storage 写入数据时使用write关键字#[storage(write)] fn write() { storage::my_storage_namespace.var.write(storage::my_storage_namespace.var.read() 1); }write(value)方法将新值写入存储变量。示例中采用读旧值 → 加一 → 写回的经典计数模式。需要强调的是即使在write标注的函数中调用了read()来获取旧值该函数在语义上仍被归为写入主导因此标注#[storage(write)]即可编译器关心的是函数整体是否会写存储。读写#[storage(read, write)]当函数既读又写 storage 时将read与write两个关键字以逗号分隔同时写出#[storage(read, write)] fn read_write() { let var storage::my_storage_namespace.var.read(); storage::my_storage_namespace.var.write(var 1); }这是三种标注中表达最完整的一种明确告知编译器该函数对存储是读 写双重访问。与上例不同这里先将读出的值绑定到局部变量var再基于var计算新值写回代码意图更清晰也更符合 read-write.md 中推荐的读变量 → 计算 → 写回模式。实战演练一个完整的读写计数合约为便于直接运行这里基于仓库中的另一个完整示例 code/operations/storage/reading_writing_to_storage/src/main.sw给出一个不含命名空间、更简洁的完整合约contract; storage { counter: u64 0, } // 只读取出当前计数 #[storage(read)] fn read() { let counter storage.counter.read(); } // 只写计数器加一 #[storage(write)] fn write() { storage.counter.write(storage.counter.read() 1); } // 读写取出并更新 #[storage(read, write)] fn read_write() { let counter storage.counter.read(); storage.counter.write(counter 1); }使用要点顶层存储变量通过storage.counter访问命名空间内的变量则通过storage::my_storage_namespace.var访问二者等价只是寻址层级不同存储变量的初始值在 storage 初始化 时确定storage块内每个变量都必须提供名称、类型与默认值如counter: u64 0若某个函数既不需要读也不需要写存储直接省略#[storage]标注即可编译器将其视为纯函数。底层机制read()/write()与标准库实现#[storage]标注只是编译期的纯度声明真正完成链上数据读写的是存储变量暴露的read()与write()方法。这两者的实现位于 Sway 标准库 sway-lib-std/src/storage.sw与文档 operations/storage/index.md 中提到的 storage 库一致。标准库为常见内置类型如u64、bool、str等实现了存储变量访问器并通过 Sway 的__state_load_word/__state_store_word等底层内在函数intrinsics与 Fuel 虚拟机状态存储交互对于更复杂的数据结构如StorageMap、StorageVec标准库还提供额外的 storage 库能力但使用这些结构时同样必须遵守#[storage]纯度标注规则从仓库 sway-lib-std/src/storage.sw 的源码结构可以推断所有存储访问都统一经由标准库封装合约开发者通过#[storage(read)]/#[storage(write)]声明访问意图编译器据此校验纯度一致性并生成相应的存储读写指令。这种属性声明在前、标准库执行在后的分层设计使 Sway 既能保证链上状态访问的语义安全又能把底层的状态读写细节完全封装在标准库中。常见问题与注意事项纯净函数不要标注既不读也不写的函数若加上#[storage]反而与语义不符编译器会将其识别为存在未使用的存储声明。保持用到才标、按需标注。读写组合顺序无关#[storage(read, write)]与#[storage(write, read)]语义等价关键字本身不区分先后。构造函数与存储初始化在 storage 初始化 中复杂类型如结构体既可以在storage块中显式写出所有字段也可以通过关联构造函数constructor封装默认值——但该构造函数必须能在编译期求值为常量这一点与#[storage]标注函数无关仅影响存储变量的初始布局。storage访问必须显式Sway 不允许隐式读写存储变量必须用storage.或storage::前缀显式指明来源这与 read-write.md 中必须显式指示变量来自 storage 而非局部作用域的规则一致。延伸阅读存储操作总览了解存储初始化、读写、命名空间与标准库扩展存储读写详解storage.前缀与内置类型访问方式存储初始化storage块的声明规则与构造函数初始化存储命名空间命名空间内变量的访问语法标准库 storage 实现read()/write()的底层实现属性总览Sway 全部内建属性【免费下载链接】sway Empowering everyone to build reliable and efficient smart contracts.项目地址: https://gitcode.com/GitHub_Trending/sw/sway创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考