Rust计算购物车总价始终为0的问题排查与解决
购物车总价计算始终为0的问题排查与修复
问题场景
你定义了在线商店购物车相关的Rust结构体:
pub struct UserTransationHistory<T: Config> { transactionId: <T as frame_system::Config>::Hash, items: Vec<UserBasketItemItem<T>>, customerPay: bool, confirmPay: bool, storeOwner: T::AccountId, storeId: <T as frame_system::Config>::Hash, } pub struct UserBasketItemItem<T: Config> { itemId: <T as frame_system::Config>::Hash, count: u32, price: u32, }
尝试计算购物车总价时,即使购物车中添加了价格为10的商品,日志输出的total_price始终为0:
Baskets::<T>::mutate(storeId, |basket| -> DispatchResult { match basket { Some(basket) => { let mut total_price = 0; basket.items.iter().map(|x| total_price += x.price).rev(); log::info!("**************** Total Price {:?}", total_price); Ok(()) }, _ => Err(<Error<T>>::StoreItemNotFound.into()), } });
问题原因
核心问题是Rust迭代器的惰性特性:
map方法仅定义了迭代器的元素转换逻辑,不会主动触发遍历执行。你写的这行代码只是创建了一个未被使用的迭代器,根本没有遍历任何商品,因此total_price的初始值0从未被修改。- 此外,用
map执行修改外部变量的副作用操作,违背了map用于纯转换操作的设计意图。
修复方案
方案1:使用fold方法(推荐,函数式风格)
fold是迭代器的聚合方法,专门用于累加计算总和,无需外部可变变量:
Baskets::<T>::mutate(storeId, |basket| -> DispatchResult { match basket { Some(basket) => { let total_price: u32 = basket.items.iter().fold(0, |acc, item| acc + item.price); log::info!("**************** Total Price {:?}", total_price); Ok(()) }, _ => Err(<Error<T>>::StoreItemNotFound.into()), } });
方案2:使用普通for循环(命令式风格,直观易懂)
直接遍历商品列表,手动累加价格:
Baskets::<T>::mutate(storeId, |basket| -> DispatchResult { match basket { Some(basket) => { let mut total_price = 0; for item in &basket.items { total_price += item.price; } log::info!("**************** Total Price {:?}", total_price); Ok(()) }, _ => Err(<Error<T>>::StoreItemNotFound.into()), } });
内容的提问来源于stack exchange,提问作者Kianoush Dortaj
相关产品推荐
相关产品推荐

