传递文本参数
本教程提供了默认程序的简单变体,允许您将单个文本参数传递给单个参与者,编译代码以创建容器智能合约,然后检索参数。 在本文档中,术语容器智能合约和容器被视为同义词。
本教程说明了如何使用 Candid 接口描述语言 (IDL) 在终端中的命令行上传递参数,以及如何修改程序以允许它接受多个文本参数值。
创建一个新项目
要为本教程创建一个新项目:
-
如果您还没有打开一个终端shell,请在您的本地计算机上打开一个终端外壳。
-
更改为您用于 Internet Computer 项目的文件夹(如果您正在使用一个)。
-
通过运行以下命令创建一个新项目:
dfx new location_hello
-
通过运行以下命令切换到您的项目目录:
cd location_hello
修改默认配置
在Explore the default project 教程中,您看到创建一个新项目会在您的项目目录中添加一个默认的`dfx.json` 配置文件。 您应始终查看文件中的默认设置,以验证信息是否准确反映了您要使用的项目设置。 对于本教程,您将修改默认配置以删除未使用的设置。
修改 dfx.json
配置文件中的设置:
-
在文本编辑器中打开
dfx.json
配置文件。 -
检查
location_hello
项目的默认设置。 -
删除所有不必要的配置设置。
由于本教程不涉及创建任何前端资产,因此您可以从文件中删除所有
location_hello_assets
配置设置。 -
保存更改并关闭文件以继续。
修改默认程序
在Explore the default project 教程中,您看到创建一个新项目会创建一个带有模板 main.mo
文件的默认 src
目录。
修改默认模板源代码:
-
在文本编辑器中打开
src/location_hello/main.mo
源代码文件。 -
修改默认源代码,将
greet
函数替换为location
函数,将name
参数替换为city
参数。例如:
actor { public func location(city : Text) : async Text { return "Hello, " # city # "!"; }; };
-
保存更改并关闭文件以继续。
启动本地容器执行环境
在构建项目之前,您需要连接到本地容器执行环境或 Internet Computer 区块链主网。
在本地启动容器执行环境需要一个 dfx.json
文件,因此您应该确保您位于项目的根目录中。
对于本教程,您应该有两个独立的终端 shell,以便您可以在一个终端中启动和查看网络操作并在另一个终端中管理您的项目。
启动本地容器执行环境:
-
在本地计算机上打开一个新的终端窗口或选项卡。
-
如有必要,导航到项目的根目录。
-
您现在应该打开了两个终端。
-
您应该将 project 目录 作为您的 current 工作目录。
-
-
通过运行以下命令在本地计算机上启动容器执行环境:
dfx start
如果系统提示您允许或拒绝传入的网络连接,请单击 Allow。
-
让显示网络操作的终端保持打开状态,然后将注意力转移到创建项目的原始终端。
注册、构建和部署 dapp
连接到本地容器执行环境后,您可以在本地注册、构建和部署 dapp。
要在本地部署 dapp:
-
如果需要,请检查您是否仍在项目的根目录中。
-
通过运行以下命令来注册、构建和部署您的应用程序:
dfx deploy
dfx deploy
命令输出显示有关它执行的操作的信息。
传递一个文本参数
您现在在本地容器执行环境中部署了一个程序作为 canister 智能合约,并且可以使用 dfx canister call
命令测试您的程序。
要测试您在本地部署的程序:
-
在程序中调用
location
方法并通过运行以下命令传递类型为text
的city
参数:dfx canister call location_hello location "San Francisco"
因为这种情况下的参数在
San
和Francisco
之间包含一个空格,所以您需要将参数括在引号中。 该命令显示类似于以下内容的输出:("Hello, San Francisco!")
如果参数不包含需要将文本括在引号内的空格,则可以允许 Candid 接口描述语言推断数据类型,如下所示:
dfx canister call location_hello location Paris
Candid 将数据类型推断为“文本”,并将程序的输出作为文本返回,如下所示:
("Hello, Paris!")
-
在程序中调用
location
方法并使用用于 Text 参数的 Candid 接口描述语言语法显式传递您的city
参数:dfx canister call location_hello location '("San Francisco and Paris")'
该命令显示类似于以下内容的输出:
("Hello, San Francisco and Paris!")
因为您的程序只接受一个文本参数,所以指定多个字符串只返回第一个参数。
例如,如果您尝试以下命令:
dfx canister call location_hello location '("San Francisco","Paris","Rome")'
只有第一个参数——
("Hello, San Francisco!")
——被返回。
修改程序中的源代码
要扩展您在本教程中学到的知识,您可能需要尝试修改源代码以返回不同的结果。
例如,您可能想要修改 location
函数以返回多个城市名称。
要尝试修改本教程的源代码:
-
在文本编辑器中打开
dfx.json
配置文件并将默认的location_hello
设置更改为favorite_cities
。对于这一步,您应该修改容器名称和容器智能合约的主程序路径以使用`favorite_cities`。
-
保存您的更改并关闭
dfx.json
文件以继续。 -
通过运行以下命令,复制
location_hello
源文件目录以匹配dfx.json
配置文件中指定的名称:cp -r src/location_hello src/favorite_cities
-
在文本编辑器中打开
src/favorite_cities/main.mo
文件。 -
复制并粘贴以下代码示例,将
location
函数替换为两个新函数。例如:
actor { public func location(cities : [Text]) : async Text { return "Hello, from " # (debug_show cities) # "!"; }; public func location_pretty(cities : [Text]) : async Text { var str = "Hello from "; for (city in cities.vals()) { str := str # city #", "; }; return str # "bon voyage!"; } };
您可能会注意到此代码示例中的
Text
被方括号 ([ ]
) 括起来。Text
本身代表 UTF-8 字符的集合。 类型周围的方括号表示它是该类型的*array*。 因此,在这种情况下,[Text]
表示一个 UTF-8 字符集合的数组,使程序能够接受和返回多个文本字符串。代码示例还使用了数组的“apply”操作的基本格式,可以抽象为:
public func apply<A, B>(fs : [A -> B], xs : [A]) : [B] { var ys : [B] = []; for (f in fs.vals()) { ys := append<B>(ys, map<A, B>(f, xs)); }; ys; };
有关对数组执行操作的函数的信息,请参阅 Motoko 基础库或_Motoko 编程语言参考_中对 Array 模块的描述。 另一个专注于使用数组的例子,见Quicksort link:https://github.com/dfinity/examples /[示例] 存储库。
-
通过运行以下命令注册、构建和部署 dapp:
dfx deploy
-
在程序中调用
location
方法并使用 Candid 接口描述语法通过运行以下命令传递您的city
参数:dfx canister call favorite_cities location '(vec {"San Francisco";"Paris";"Rome"})'
该命令使用 Candid 接口描述语法
(vec { val1; val2; val3; })
返回值向量。 有关 Candid 界面描述语言的更多信息,请参见链接:../../candid-guide/candid-intro.html[Candid] 语言指南。此命令显示类似于以下内容的输出:
("Hello, from ["San Francisco", "Paris", "Rome"]!")
-
在程序中调用
location_pretty
方法并使用接口描述语法通过运行以下命令传递您的city
参数:dfx canister call favorite_cities location_pretty '(vec {"San Francisco";"Paris";"Rome"})'
该命令显示类似于以下内容的输出:
("Hello from San Francisco, Paris, Rome, bon voyage!")
在浏览器中测试功能
容器接口描述语言(通常称为 Candid 或更一般地称为 IDL)为指定容器智能合约的签名提供了一种通用语言。 Candid 为您提供了一种统一的方式来与用不同语言编写或使用不同工具访问的容器智能合约进行交互。 例如,无论底层程序是原生 Rust、JavaScript 还是 Motoko,Candid 都能提供一致的服务视图。 Candid 还启用了不同的工具——例如`dfx` 命令行界面和网络神经系统 dapp——来共享服务的通用描述。
基于 actor 的类型签名,Candid 还提供了一个 Web 界面,允许您调用容器函数进行测试和调试。
使用 dfx deploy
或 dfx canister install
命令在本地容器执行环境中部署项目后,您可以在浏览器中访问 Candid Web 界面端点。
此 Web 界面 — Candid UI — 以表单形式公开服务描述,使您无需编写任何前端代码即可快速查看和测试功能并尝试输入不同的数据类型。
要使用 Candid Web 界面测试容器功能:
dfx canister id __Candid_UI
命令查找与当前项目关联的 Candid UI 容器标识符。+
dfx canister id __Candid_UI
+ 该命令显示 Candid UI 的容器标识符,输出类似于以下内容:
+
r7inp-6aaaa-aaaaa-aaabq-cai
+ . 复制 Candid UI 容器标识符,使其在剪贴板中可用。 . 如果您已停止本地容器执行环境,请通过运行以下命令在本地重新启动它:
+
dfx start --background
-
打开浏览器并导航到
dfx.json
配置文件中指定的地址和端口号。默认情况下,本地容器执行环境绑定到`127.0.0.1:8000`地址和端口号。
-
将所需的
canisterId
参数和dfx canister id __Candid_UI
命令返回的 Candid UI 容器标识符添加到 URL。例如,完整的 URL 应该类似于以下内容,但带有由
dfx canister id __Candid_UI
命令返回的`CANDID-UI-CANISTER-IDENTIFIER`:http://127.0.0.1:8000/?canisterId=<CANDID-UI-CANISTER-IDENTIFIER>
例如,对于 Candid UI 的示例容器标识符,如上所示,可能如下所示:
http://127.0.0.1:8000/?canisterId=r7inp-6aaaa-aaaaa-aaabq-cai
然后,浏览器会显示一个表单供您指定容器标识符或选择 Candid 描述 (
.did
) 文件。 请注意,此字段是指您要与之交互的容器的容器标识符(与我们在上一步中使用的 Candid UI 的容器标识符相反)。 -
在 Provide a canister ID 字段中指定要测试的容器的容器标识符,然后单击 Go 以显示服务描述。
如果您不确定要使用哪个容器标识符,可以运行
dfx canister id
命令来查找特定容器名称的标识符。 例如,要获取名为my_counter
的容器的容器标识符,您可以使用:dfx canister id my_counter
-
查看 dapp 中定义的函数调用和类型列表。
-
为函数键入适当类型的值或单击 Random 生成值,然后单击 Call 或 Query 以查看结果。
请注意,根据数据类型,Candid 界面可能会显示用于测试功能的其他配置设置。 例如,如果一个函数接受一个数组,您可能需要在输入值之前指定数组中的项目数。
在此示例中,每个函数都接受一个文本字符串数组。 因此,您首先选择数组的长度,然后为每个项目设置值,然后单击调用。