Aptos

2025年09月05日更新 4 人订阅
原价: ¥ 2.2 限时优惠
专栏简介 Aptos 开发实战:从环境搭建到第一个 Hello World Aptos 开发指南:在 JetBrains 编辑器中配置运行、编译、测试与发布部署,实现更高效开发 Aptos 区块链智能合约入门:使用 Move 实现消息存储与检索 Aptos Move 语言中的变量管理与内存所有权机制详解 Aptos Move 编程语言中的四大基础类型解析:UINT、STRING、BOOL 与 ADDRESS 深入解读 APTOS-MOVE 中的 Vector 向量核心特性与操作 深入理解APTOS-MOVE中的函数修饰符:核心概念与应用 深入解读 Aptos Move 的 Struct 特性与四大能力 Aptos Move 控制流解析:IF、WHILE与LOOP的深入解读 Aptos Move 模块的特性与实操指南:模块引用与作用域管理 Aptos Move 模块的发布与交互:完整指南 深入理解 Aptos Move 中的 Object 创建与管理 深入探索 Aptos Move:Object 配置与实操指南 使用 Aptos Move 实现随机数生成:从 AIP-41 到实战操作 Aptos Move 实践指南:构建并部署同质化代币水龙头 (FA Faucet) Aptos Move NFT 项目实操指南:从开发到部署全流程解析 Aptos Move 开发入门:从环境搭建到合约部署全流程实录 Aptos Move 入门:从零到一的合约开发与测试实战 Move 语言核心:布尔逻辑与地址类型的实战精解 深入 Aptos Move:从public到friend,函数可见性详解 Aptos Move 编程:for、while 与 loop 循环的实战详解 Aptos Move 安全编程:abort 与 assert! 错误处理实战 Aptos Move 实战:基础运算与比较逻辑的实现与测试 Aptos Move 性能优化:位运算与移位操作实战 Aptos Move 实战:as 关键字与整数类型转换技巧 Aptos Move DeFi 实战:从零构建流动性池兑换逻辑 Aptos Move 实战:用 signer 实现合约所有权与访问控制 Aptos Move 核心安全:& 与 &mut 引用机制详解 Aptos Move 实战:全面掌握 SimpleMap 的增删改查

Aptos Move 实战:全面掌握 SimpleMap 的增删改查

AptosMove实战:全面掌握SimpleMap的增删改查在智能合约开发中,管理动态的数据集合是一项基本功。键值对(Key-Value)映射作为最高效、最常用的数据结构之一,是每个开发者都必须掌握的工具。在AptosMove中,SimpleMap就为我们提供了这样一个基础而强大的

Aptos Move 实战:全面掌握 SimpleMap 的增删改查

在智能合约开发中,管理动态的数据集合是一项基本功。键值对(Key-Value)映射作为最高效、最常用的数据结构之一,是每个开发者都必须掌握的工具。在 Aptos Move 中,SimpleMap 就为我们提供了这样一个基础而强大的实现。

这篇实战教程的目标只有一个:带你全面掌握 SimpleMap 的增删改查(CRUD)。我们将从最基础的创建和添加操作开始,逐步学习如何读取、移除,并最终掌握强大的更新或插入 (upsert) 功能。更重要的是,你将学会如何将这些操作封装成清晰的辅助函数,并通过单元测试来验证一个映射(Map)从诞生到变化的完整生命周期。

实操

Aptos Move Maps

示例一

module net2dev_addr::MapsDemo {
    use std::simple_map::{SimpleMap, Self};
    use std::string::{String, utf8};

    fun create_map(): SimpleMap<u64, String> {
        let my_map: SimpleMap<u64, String> = simple_map::create();
        my_map.add(1, utf8(b"UAE"));
        my_map.add(2, utf8(b"RUS"));
        my_map.add(3, utf8(b"MEX"));
        my_map.add(4, utf8(b"COL"));
        my_map
    }

    #[test_only]
    use std::debug::print;

    #[test]
    fun test_map() {
        let my_map = create_map();
        assert!(my_map.contains_key(&1), 0);
        assert!(my_map.contains_key(&2), 1);
        assert!(my_map.contains_key(&3), 2);
        assert!(my_map.contains_key(&4), 3);
        assert!(my_map.length() == 4, 4);

        let country = my_map.borrow(&1);
        assert!(country == &utf8(b"UAE"), 5);
        print(country);

        let country = my_map.borrow(&2);
        assert!(country == &utf8(b"RUS"), 6);
        print(country);

        let country = my_map.borrow(&3);
        assert!(country == &utf8(b"MEX"), 7);
        print(country);

        let country = my_map.borrow(&4);
        assert!(country == &utf8(b"COL"), 8);
        print(country);
    }
}

这段 Aptos Move 代码通过一个名为 MapsDemo 的模块,演示了标准库中基础键值对数据结构 SimpleMap 的用法。模块中的 create_map 函数展示了如何初始化一个空映射并用多个键值对(在此例中是 u64 整数键到 String 字符串值)进行填充。而 test_map 单元测试则验证了该映射的功能,它通过执行一系列常用操作——如使用 contains_key 检查键是否存在、使用 length 获取大小、以及使用 borrow 读取值——并利用 assert! 语句来确保所有操作都返回了预期的正确结果。

测试

➜ aptos move test
INCLUDING DEPENDENCY AptosFramework
INCLUDING DEPENDENCY AptosStdlib
INCLUDING DEPENDENCY MoveStdlib
BUILDING my-dapp
Running Move unit tests
[debug] "UAE"
[debug] "RUS"
[debug] "MEX"
[debug] "COL"
[ PASS    ] 0x48daaa7d16f1a59929ece03157b8f3e4625bc0a201988ac6fea9b38f50db5ef3::MapsDemo::test_map
Test result: OK. Total tests: 1; passed: 1; failed: 0
{
  "Result": "Success"
}

这个测试结果表明,你的 my-dapp 项目已成功通过其全部单元测试。在成功编译项目后,测试框架执行了 MapsDemo 模块中定义的唯一一个测试函数 test_map。日志中的 [debug] 行清晰地打印出了 "UAE"、"RUS" 等字符串,这些正是测试代码在执行过程中通过 borrow 方法从 SimpleMap 中成功读取出的值。最终的 [ PASS ] 状态,结合 Test result: OK 的总结陈述,共同确认了该测试用例顺利完成,意味着其内部所有关于 contains_keylengthborrowassert! 断言均已满足,证明了你代码中对 SimpleMap 的各项操作逻辑完全正确。

示例二

module net2dev_addr::MapsDemo {
    use std::simple_map::{SimpleMap, Self};
    use std::string::{String, utf8};

    fun create_map(): SimpleMap<u64, String> {
        let my_map: SimpleMap<u64, String> = simple_map::create();
        my_map.add(1, utf8(b"UAE"));
        my_map.add(2, utf8(b"RUS"));
        my_map.add(3, utf8(b"MEX"));
        my_map.add(4, utf8(b"COL"));
        my_map
    }

    fun check_map_length(my_map: SimpleMap<u64, String>): u64 {
        my_map.length()
    }

    #[test_only]
    use std::debug::print;

    #[test]
    fun test_map() {
        let my_map = create_map();
        assert!(my_map.contains_key(&1), 0);
        assert!(my_map.contains_key(&2), 1);
        assert!(my_map.contains_key(&3), 2);
        assert!(my_map.contains_key(&4), 3);
        assert!(my_map.length() == 4, 4);

        let country = my_map.borrow(&1);
        assert!(country == &utf8(b"UAE"), 5);
        print(country);

        let country = my_map.borrow(&2);
        assert!(country == &utf8(b"RUS"), 6);
        print(country);

        let country = my_map.borrow(&3);
        assert!(country == &utf8(b"MEX"), 7);
        print(country);

        let country = my_map.borrow(&4);
        assert!(country == &utf8(b"COL"), 8);
        print(country);

        let length = check_map_length(my_map);
        assert!(length == 4, 9);
        print(&length);
    }
}

这段 Aptos Move 代码通过一个名为 MapsDemo 的模块,演示了 SimpleMap 的用法以及创建辅助函数 (helper function) 的概念。在原有的 create_map 函数基础上,该模块新增了一个 check_map_length 函数,其唯一职责就是接收一个映射并返回它的大小。主单元测试 test_map 现在验证了整个工作流程:它首先直接检查映射的内容和属性,随后调用新增的 check_map_length 辅助函数并断言其返回值,从而确认了直接的映射操作封装后的辅助函数都能正确工作。

测试

➜ aptos move test
INCLUDING DEPENDENCY AptosFramework
INCLUDING DEPENDENCY AptosStdlib
INCLUDING DEPENDENCY MoveStdlib
BUILDING my-dapp
Running Move unit tests
[debug] "UAE"
[debug] "RUS"
[debug] "MEX"
[debug] "COL"
[debug] 4
[ PASS    ] 0x48daaa7d16f1a59929ece03157b8f3e4625bc0a201988ac6fea9b38f50db5ef3::MapsDemo::test_map
Test result: OK. Total tests: 1; passed: 1; failed: 0
{
  "Result": "Success"
}

这个测试结果表明,你的 my-dapp 项目已成功通过其全部单元测试。在成功编译项目后,测试框架执行了 MapsDemo 模块中定义的唯一一个测试函数 test_map。日志中的 [debug] 输清晰地展示了测试的全过程:它首先打印出了从 Map 中成功读取的 "UAE", "RUS" 等四个字符串值,最后打印出的数字 4 则是新增的 check_map_length 辅助函数返回的正确长度。最终的 [ PASS ] 状态和 Test result: OK 的总结陈述,共同确认了该测试用例顺利完成,证明了你代码中直接的 Map 操作以及封装后的辅助函数逻辑都完全正确。

示例三

module net2dev_addr::MapsDemo {
    use std::simple_map::{SimpleMap, Self};
    use std::string::{String, utf8};

    fun create_map(): SimpleMap<u64, String> {
        let my_map: SimpleMap<u64, String> = simple_map::create();
        my_map.add(1, utf8(b"UAE"));
        my_map.add(2, utf8(b"RUS"));
        my_map.add(3, utf8(b"MEX"));
        my_map.add(4, utf8(b"COL"));
        my_map
    }

    fun check_map_length(my_map: SimpleMap<u64, String>): u64 {
        my_map.length()
    }

    fun check_map_contains(my_map: SimpleMap<u64, String>, key: u64): bool {
        my_map.contains_key(&key)
    }

    fun remove_from_map(my_map: SimpleMap<u64, String>, key: u64): SimpleMap<u64, String> {
        my_map.remove(&key);
        my_map
    }

    fun upsert_map(
        my_map: SimpleMap<u64, String>,
        key: u64,
        value: String
    ): SimpleMap<u64, String> {
        my_map.upsert(key, value);
        my_map
    }

    #[test_only]
    use std::debug::print;

    #[test]
    fun test_map() {
        let my_map = create_map();
        assert!(my_map.contains_key(&1), 0);
        assert!(my_map.contains_key(&2), 1);
        assert!(my_map.contains_key(&3), 2);
        assert!(my_map.contains_key(&4), 3);
        assert!(my_map.length() == 4, 4);

        let country = my_map.borrow(&1);
        assert!(country == &utf8(b"UAE"), 5);
        print(country);

        let country = my_map.borrow(&2);
        assert!(country == &utf8(b"RUS"), 6);
        print(country);

        let country = my_map.borrow(&3);
        assert!(country == &utf8(b"MEX"), 7);
        print(country);

        let country = my_map.borrow(&4);
        assert!(country == &utf8(b"COL"), 8);
        print(country);

        let length = check_map_length(my_map);
        assert!(length == 4, 9);
        print(&length);

        let new_map = remove_from_map(my_map, 2);
        let length = check_map_length(new_map);
        assert!(length == 3, 10);
        print(&length);
        print(&new_map);

        let new_map = upsert_map(new_map, 2, utf8(b"CAN"));
        let length = check_map_length(new_map);
        assert!(length == 4, 11);
        print(&length);
        print(&new_map);

        let b = check_map_contains(new_map, 2);
        assert!(b == true, 12);
        print(&b);
    }
}

这段 Aptos Move 代码扩展了 MapsDemo 模块,通过将更全面的 SimpleMap 操作封装到各自的辅助函数中来进行演示。除了创建和读取映射,代码新增了用于检查键是否存在 (check_map_contains)、移除键值对 (remove_from_map) 以及插入或更新值 (upsert_map) 的函数。其主单元测试 test_map 现在演示了该映射的一个完整生命周期:它首先创建并验证初始数据,接着调用辅助函数移除一个元素,然后使用 upsert 将该元素以不同的值重新加回,并通过 assert! 语句在每个阶段都验证了映射的状态

测试

➜ aptos move test
INCLUDING DEPENDENCY AptosFramework
INCLUDING DEPENDENCY AptosStdlib
INCLUDING DEPENDENCY MoveStdlib
BUILDING my-dapp
Running Move unit tests
[debug] "UAE"
[debug] "RUS"
[debug] "MEX"
[debug] "COL"
[debug] 4
[debug] 3
[debug] 0x1::simple_map::SimpleMap<u64, 0x1::string::String> {
  data: [
    0x1::simple_map::Element<u64, 0x1::string::String> {
      key: 1,
      value: "UAE"
    },
    0x1::simple_map::Element<u64, 0x1::string::String> {
      key: 4,
      value: "COL"
    },
    0x1::simple_map::Element<u64, 0x1::string::String> {
      key: 3,
      value: "MEX"
    }
  ]
}
[debug] 4
[debug] 0x1::simple_map::SimpleMap<u64, 0x1::string::String> {
  data: [
    0x1::simple_map::Element<u64, 0x1::string::String> {
      key: 1,
      value: "UAE"
    },
    0x1::simple_map::Element<u64, 0x1::string::String> {
      key: 4,
      value: "COL"
    },
    0x1::simple_map::Element<u64, 0x1::string::String> {
      key: 3,
      value: "MEX"
    },
    0x1::simple_map::Element<u64, 0x1::string::String> {
      key: 2,
      value: "CAN"
    }
  ]
}
[debug] true
[ PASS    ] 0x48daaa7d16f1a59929ece03157b8f3e4625bc0a201988ac6fea9b38f50db5ef3::MapsDemo::test_map
Test result: OK. Total tests: 1; passed: 1; failed: 0
{
  "Result": "Success"
}

这个测试结果表明,你的 my-dapp 项目已成功通过其全部单元测试。在成功编译项目后,唯一的测试函数 test_map 被执行,其详细的 [debug] 输出清晰地记录了 SimpleMap 对象的完整生命周期:从初始内容和长度(4)的验证,到移除一个元素后其内容的变化和长度缩减为 3,再到通过 upsert 操作将键重新插入新值 "CAN" 后内容恢复且长度变回 4。最终的 [ PASS ] 状态及 Test result: OK 的总结,证明了测试中的每一步 assert! 断言均已满足,验证了你代码中对 SimpleMap 的创建、读取、移除和更新/插入等一系列连续操作的逻辑完全正确。

总结

恭喜你!通过本篇详尽的实战教程,你已经全面掌握了 Aptos Move 中 SimpleMap增删改查(CRUD)全流程。我们一起走完了创建、填充、读取、移除、再到更新/插入 (upsert) 的完整生命周期,并学习了将其操作逻辑封装成独立函数的优秀实践。

最终测试报告中每一条 [ PASS ] 记录,都证明了我们对 SimpleMap 每一步操作的逻辑都精准无误。现在,你可以自信地在自己的 Aptos Move 项目中使用 SimpleMap 来高效、安全地管理链上数据了。掌握了 SimpleMap,你已经为学习 Aptos 中更强大的 Table 等大规模存储工具打下了坚实的基础。

参考

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论