Substrate开发:如何使用try_mutate修改值为枚举的StorageMap?
问题解决
报错根因
try_mutate闭包的入参status类型为&mut Option<Gender>:这是指向Option<Gender>的可变引用,当目标AccountId不存在时*status为None,已存在时为Some(旧值)- 你的代码犯了两个典型类型错误:
- 没有对可变引用解引用,直接给引用本身赋值,类型不匹配
- 赋值内容是裸的
Gender枚举值,不是要求的Option<Gender>类型
原有逻辑bug修复
你写的前置判断逻辑完全写反了:ensure!(hotel_status == Some(Gender::Active), <Error<T>>::HotelAlreadyActive); 代表「只有酒店已经是激活状态才允许往下执行,否则抛出酒店已激活的错误」,和你预期的「已激活就报错」逻辑相反,需要调整判断条件。
修正后完整代码
#[pallet::weight(0)] pub fn activate_hotel( origin: OriginFor<T>, hotel: T::AccountId, ) -> DispatchResult { let sender = ensure_signed(origin)?; log::info!("signer ID: {:?}.", sender); let hotel_status = <HotelStatus<T>>::get(&hotel); // 修正判断:已激活则抛出错误 ensure!(hotel_status != Some(Gender::Active), <Error<T>>::HotelAlreadyActive); // 一行完成存在则修改、不存在则插入的逻辑,无需手动写insert <HotelStatus<T>>::try_mutate(hotel, |status| -> DispatchResult { *status = Some(Gender::Active); Ok(()) })?; Ok(()) }
通用操作说明
无论StorageMap的值是枚举、数字、字符串还是其他基础类型,try_mutate的使用逻辑完全统一:
- 闭包入参永远是
&mut Option<值类型> - 需要修改/插入值时先解引用
*status,赋值为Some(新值)即可 - 如果要删除对应key的存储条目,赋值为
None即可
内容的提问来源于stack exchange,提问作者ReiGun
相关产品推荐
相关产品推荐

