@ -2,7 +2,7 @@
< html lang = "en" >
< head >
< meta charset = "UTF-8" >
< title > 测试的组织结构 - Rust 程序设计语言 简体中文版< / title >
< title > 输出到`stderr`而不是`stdout` - Rust 程序设计语言 简体中文版< / title >
< meta content = "text/html; charset=utf-8" http-equiv = "Content-Type" >
< meta name = "description" content = "Rust 程序设计语言 简体中文版" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
@ -47,7 +47,7 @@
< / script >
< div id = "sidebar" class = "sidebar" >
< ul class = "chapter" > < li > < a href = "ch01-00-introduction.html" > < strong > 1.< / strong > 介绍< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch01-01-installation.html" > < strong > 1.1.< / strong > 安装< / a > < / li > < li > < a href = "ch01-02-hello-world.html" > < strong > 1.2.< / strong > Hello, World!< / a > < / li > < / ul > < / li > < li > < a href = "ch02-00-guessing-game-tutorial.html" > < strong > 2.< / strong > 猜猜看教程< / a > < / li > < li > < a href = "ch03-00-common-programming-concepts.html" > < strong > 3.< / strong > 通用编程概念< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch03-01-variables-and-mutability.html" > < strong > 3.1.< / strong > 变量和可变性< / a > < / li > < li > < a href = "ch03-02-data-types.html" > < strong > 3.2.< / strong > 数据类型< / a > < / li > < li > < a href = "ch03-03-how-functions-work.html" > < strong > 3.3.< / strong > 函数如何工作< / a > < / li > < li > < a href = "ch03-04-comments.html" > < strong > 3.4.< / strong > 注释< / a > < / li > < li > < a href = "ch03-05-control-flow.html" > < strong > 3.5.< / strong > 控制流< / a > < / li > < / ul > < / li > < li > < a href = "ch04-00-understanding-ownership.html" > < strong > 4.< / strong > 认识所有权< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch04-01-what-is-ownership.html" > < strong > 4.1.< / strong > 什么是所有权< / a > < / li > < li > < a href = "ch04-02-references-and-borrowing.html" > < strong > 4.2.< / strong > 引用 & 借用< / a > < / li > < li > < a href = "ch04-03-slices.html" > < strong > 4.3.< / strong > Slices< / a > < / li > < / ul > < / li > < li > < a href = "ch05-00-structs.html" > < strong > 5.< / strong > 结构体< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch05-01-method-syntax.html" > < strong > 5.1.< / strong > 方法语法< / a > < / li > < / ul > < / li > < li > < a href = "ch06-00-enums.html" > < strong > 6.< / strong > 枚举和模式匹配< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch06-01-defining-an-enum.html" > < strong > 6.1.< / strong > 定义枚举< / a > < / li > < li > < a href = "ch06-02-match.html" > < strong > 6.2.< / strong > < code > match< / code > 控制流运算符< / a > < / li > < li > < a href = "ch06-03-if-let.html" > < strong > 6.3.< / strong > < code > if let< / code > 简单控制流< / a > < / li > < / ul > < / li > < li > < a href = "ch07-00-modules.html" > < strong > 7.< / strong > 模块< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch07-01-mod-and-the-filesystem.html" > < strong > 7.1.< / strong > < code > mod< / code > 和文件系统< / a > < / li > < li > < a href = "ch07-02-controlling-visibility-with-pub.html" > < strong > 7.2.< / strong > 使用< code > pub< / code > 控制可见性< / a > < / li > < li > < a href = "ch07-03-importing-names-with-use.html" > < strong > 7.3.< / strong > 使用< code > use< / code > 导入命名< / a > < / li > < / ul > < / li > < li > < a href = "ch08-00-common-collections.html" > < strong > 8.< / strong > 通用集合类型< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch08-01-vectors.html" > < strong > 8.1.< / strong > vector< / a > < / li > < li > < a href = "ch08-02-strings.html" > < strong > 8.2.< / strong > 字符串< / a > < / li > < li > < a href = "ch08-03-hash-maps.html" > < strong > 8.3.< / strong > 哈希 map< / a > < / li > < / ul > < / li > < li > < a href = "ch09-00-error-handling.html" > < strong > 9.< / strong > 错误处理< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch09-01-unrecoverable-errors-with-panic.html" > < strong > 9.1.< / strong > < code > panic!< / code > 与不可恢复的错误< / a > < / li > < li > < a href = "ch09-02-recoverable-errors-with-result.html" > < strong > 9.2.< / strong > < code > Result< / code > 与可恢复的错误< / a > < / li > < li > < a href = "ch09-03-to-panic-or-not-to-panic.html" > < strong > 9.3.< / strong > < code > panic!< / code > 还是不< code > panic!< / code > < / a > < / li > < / ul > < / li > < li > < a href = "ch10-00-generics.html" > < strong > 10.< / strong > 泛型、trait 和生命周期< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch10-01-syntax.html" > < strong > 10.1.< / strong > 泛型数据类型< / a > < / li > < li > < a href = "ch10-02-traits.html" > < strong > 10.2.< / strong > trait: 定义共享的行为< / a > < / li > < li > < a href = "ch10-03-lifetime-syntax.html" > < strong > 10.3.< / strong > 生命周期与引用有效性< / a > < / li > < / ul > < / li > < li > < a href = "ch11-00-testing.html" > < strong > 11.< / strong > 测试< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch11-01-writing-tests.html" > < strong > 11.1.< / strong > 编写测试< / a > < / li > < li > < a href = "ch11-02-running-tests.html" > < strong > 11.2.< / strong > 运行测试< / a > < / li > < li > < a href = "ch11-03-test-organization.html" > < strong > 11.3.< / strong > 测试的组织结构< / a > < / li > < / ul > < / li > < / ul >
< ul class = "chapter" > < li > < a href = "ch01-00-introduction.html" > < strong > 1.< / strong > 介绍< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch01-01-installation.html" > < strong > 1.1.< / strong > 安装< / a > < / li > < li > < a href = "ch01-02-hello-world.html" > < strong > 1.2.< / strong > Hello, World!< / a > < / li > < / ul > < / li > < li > < a href = "ch02-00-guessing-game-tutorial.html" > < strong > 2.< / strong > 猜猜看教程< / a > < / li > < li > < a href = "ch03-00-common-programming-concepts.html" > < strong > 3.< / strong > 通用编程概念< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch03-01-variables-and-mutability.html" > < strong > 3.1.< / strong > 变量和可变性< / a > < / li > < li > < a href = "ch03-02-data-types.html" > < strong > 3.2.< / strong > 数据类型< / a > < / li > < li > < a href = "ch03-03-how-functions-work.html" > < strong > 3.3.< / strong > 函数如何工作< / a > < / li > < li > < a href = "ch03-04-comments.html" > < strong > 3.4.< / strong > 注释< / a > < / li > < li > < a href = "ch03-05-control-flow.html" > < strong > 3.5.< / strong > 控制流< / a > < / li > < / ul > < / li > < li > < a href = "ch04-00-understanding-ownership.html" > < strong > 4.< / strong > 认识所有权< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch04-01-what-is-ownership.html" > < strong > 4.1.< / strong > 什么是所有权< / a > < / li > < li > < a href = "ch04-02-references-and-borrowing.html" > < strong > 4.2.< / strong > 引用 & 借用< / a > < / li > < li > < a href = "ch04-03-slices.html" > < strong > 4.3.< / strong > Slices< / a > < / li > < / ul > < / li > < li > < a href = "ch05-00-structs.html" > < strong > 5.< / strong > 结构体< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch05-01-method-syntax.html" > < strong > 5.1.< / strong > 方法语法< / a > < / li > < / ul > < / li > < li > < a href = "ch06-00-enums.html" > < strong > 6.< / strong > 枚举和模式匹配< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch06-01-defining-an-enum.html" > < strong > 6.1.< / strong > 定义枚举< / a > < / li > < li > < a href = "ch06-02-match.html" > < strong > 6.2.< / strong > < code > match< / code > 控制流运算符< / a > < / li > < li > < a href = "ch06-03-if-let.html" > < strong > 6.3.< / strong > < code > if let< / code > 简单控制流< / a > < / li > < / ul > < / li > < li > < a href = "ch07-00-modules.html" > < strong > 7.< / strong > 模块< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch07-01-mod-and-the-filesystem.html" > < strong > 7.1.< / strong > < code > mod< / code > 和文件系统< / a > < / li > < li > < a href = "ch07-02-controlling-visibility-with-pub.html" > < strong > 7.2.< / strong > 使用< code > pub< / code > 控制可见性< / a > < / li > < li > < a href = "ch07-03-importing-names-with-use.html" > < strong > 7.3.< / strong > 使用< code > use< / code > 导入命名< / a > < / li > < / ul > < / li > < li > < a href = "ch08-00-common-collections.html" > < strong > 8.< / strong > 通用集合类型< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch08-01-vectors.html" > < strong > 8.1.< / strong > vector< / a > < / li > < li > < a href = "ch08-02-strings.html" > < strong > 8.2.< / strong > 字符串< / a > < / li > < li > < a href = "ch08-03-hash-maps.html" > < strong > 8.3.< / strong > 哈希 map< / a > < / li > < / ul > < / li > < li > < a href = "ch09-00-error-handling.html" > < strong > 9.< / strong > 错误处理< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch09-01-unrecoverable-errors-with-panic.html" > < strong > 9.1.< / strong > < code > panic!< / code > 与不可恢复的错误< / a > < / li > < li > < a href = "ch09-02-recoverable-errors-with-result.html" > < strong > 9.2.< / strong > < code > Result< / code > 与可恢复的错误< / a > < / li > < li > < a href = "ch09-03-to-panic-or-not-to-panic.html" > < strong > 9.3.< / strong > < code > panic!< / code > 还是不< code > panic!< / code > < / a > < / li > < / ul > < / li > < li > < a href = "ch10-00-generics.html" > < strong > 10.< / strong > 泛型、trait 和生命周期< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch10-01-syntax.html" > < strong > 10.1.< / strong > 泛型数据类型< / a > < / li > < li > < a href = "ch10-02-traits.html" > < strong > 10.2.< / strong > trait: 定义共享的行为< / a > < / li > < li > < a href = "ch10-03-lifetime-syntax.html" > < strong > 10.3.< / strong > 生命周期与引用有效性< / a > < / li > < / ul > < / li > < li > < a href = "ch11-00-testing.html" > < strong > 11.< / strong > 测试< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch11-01-writing-tests.html" > < strong > 11.1.< / strong > 编写测试< / a > < / li > < li > < a href = "ch11-02-running-tests.html" > < strong > 11.2.< / strong > 运行测试< / a > < / li > < li > < a href = "ch11-03-test-organization.html" > < strong > 11.3.< / strong > 测试的组织结构< / a > < / li > < / ul > < / li > < li > < a href = "ch12-00-an-io-project.html" > < strong > 12.< / strong > 一个 I/O 项目< / a > < / li > < li > < ul class = "section" > < li > < a href = "ch12-01-accepting-command-line-arguments.html" > < strong > 12.1.< / strong > 接受命令行参数< / a > < / li > < li > < a href = "ch12-02-reading-a-file.html" > < strong > 12.2.< / strong > 读取文件< / a > < / li > < li > < a href = "ch12-03-improving-error-handling-and-modularity.html" > < strong > 12.3.< / strong > 增强错误处理和模块化< / a > < / li > < li > < a href = "ch12-04-testing-the-librarys-functionality.html" > < strong > 12.4.< / strong > 测试库的功能< / a > < / li > < li > < a href = "ch12-05-working-with-environment-variables.html" > < strong > 12.5.< / strong > 处理环境变量< / a > < / li > < li > < a href = "ch12-06-writing-to-stderr-instead-of-stdout.html" > < strong > 12.6.< / strong > 输出到< code > stderr< / code > 而不是< code > stdout< / code > < / a > < / li > < / ul > < / li > < / ul >
< / div >
< div id = "page-wrapper" class = "page-wrapper" >
@ -6038,6 +6038,136 @@ mod tests {
< / figure >
< p > 因为测试也不过是 Rust 代码而< code > tests< / code > 也只是另一个模块,我们完全可以在一个测试中导入并调用< code > internal_adder< / code > 。如果你并不认为私有函数应该被测试, Rust 也不会强迫你这么做。< / p >
< a class = "header" href = "#集成测试" name = "集成测试" > < h3 > 集成测试< / h3 > < / a >
< p > 在 Rust 中,集成测试对于需要测试的库来说是完全独立。他们同其他代码一样使用库文件。他们的目的是测试库的个个部分结合起来能否正常工作。每个能正确运行的代码单元集成在一起也可能会出现问题,所以集成测试的覆盖率也是很重要的。< / p >
< a class = "header" href = "#tests-目录" name = "tests-目录" > < h4 > < em > tests< / em > 目录< / h4 > < / a >
< p > Cargo 支持位于 < em > tests< / em > 目录中的集成测试。如果创建它并放入 Rust 源文件, Cargo 会将每一个文件当作单独的 crate 来编译。让我们试一试!< / p >
< p > 首先,在项目根目录创建一个 < em > tests< / em > 目录,挨着 < em > src< / em > 目录。接着新建一个文件 < em > tests/integration_test.rs< / em > ,并写入列表 11-7 中的代码:< / p >
< figure >
< span class = "filename" > Filename: tests/integration_test.rs< / span >
< pre > < code class = "language-rust,ignore" > extern crate adder;
#[test]
fn it_adds_two() {
assert_eq!(4, adder::add_two(2));
}
< / code > < / pre >
< figcaption >
< p > Listing 11-7: An integration test of a function in the < code > adder< / code > crate< / p >
< / figcaption >
< / figure >
< p > 在开头使用了< code > extern crate adder< / code > ,单元测试中并不需要它。< code > tests< / code > 目录中的每一个测试文件都是完全独立的 crate, 所以需要在每个文件中导入我们的库。这也就是为何< code > tests< / code > 是编写集成测试的绝佳场所:他们像任何其他用户那样,需要将库导入 crate 并只能使用公有 API。< / p >
< p > 这个文件中也不需要< code > tests< / code > 模块。除非运行测试否则整个文件夹都不会被编译,所以无需将任何部分标记为< code > #[cfg(test)]< / code > 。另外每个测试文件都被隔离进其自己的 crate 中,无需进一步隔离测试代码。< / p >
< p > 让我们运行集成测试,同样使用< code > cargo test< / code > 来运行:< / p >
< pre > < code > $ cargo test
Compiling adder v0.1.0 (file:///projects/adder)
Running target/debug/deps/adder-abcabcabc
running 1 test
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Running target/debug/integration_test-952a27e0126bb565
running 1 test
test it_adds_two ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Doc-tests adder
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
< / code > < / pre >
< p > 现在有了三个部分的输出:单元测试、集成测试和文档测试。注意当在任何 < em > src< / em > 目录的文件中增加单元测试时,单元测试部分的对应输出也会增加。增加集成测试文件中的测试函数也会对应增加输出。如果在 < em > tests< / em > 目录中增加集成测试< strong > 文件< / strong > ,则会增加更多集成测试部分:一个文件对应一个部分。< / p >
< p > 为< code > cargo test< / code > 指定测试函数名称参数也会匹配集成测试文件中的函数。为了只运行某个特定集成测试文件中的所有测试,可以使用< code > cargo test< / code > 的< code > --test< / code > 参数:< / p >
< pre > < code > $ cargo test --test integration_test
Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
Running target/debug/integration_test-952a27e0126bb565
running 1 test
test it_adds_two ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
< / code > < / pre >
< a class = "header" href = "#集成测试中的子模块" name = "集成测试中的子模块" > < h4 > 集成测试中的子模块< / h4 > < / a >
< p > 随着集成测试的增加,你可能希望在 < code > tests< / code > 目录增加更多文件, 例如根据测试的功能来将测试分组。正如我们之前提到的, 这是可以的, Cargo 会将每一个文件当作一个独立的 crate。< / p >
< p > 最终,可能会有一系列在所有集成测试中通用的帮助函数,例如建立通用场景的函数。如果你将这些函数提取到 < em > tests< / em > 目录的一个文件中,比如说 < em > tests/common.rs< / em > ,则这个文件将会像这个目录中的其他包含测试的 Rust 文件一样被编译进一个单独的 crate 中。它也会作为一个独立的部分出现在测试输出中。因为这很可能不是你所希望的,所以建议在子目录中使用 < em > mod.rs< / em > 文件,比如 < em > tests/common/mod.rs< / em > ,来放置帮助函数。< em > tests< / em > 的子目录不会被作为单独的 crate 编译或者作为单独的部分出现在测试输出中。< / p >
< a class = "header" href = "#二进制-crate-的集成测试" name = "二进制-crate-的集成测试" > < h4 > 二进制 crate 的集成测试< / h4 > < / a >
< p > 如果项目是二进制 crate 并且只包含 < em > src/main.rs< / em > 而没有 < em > src/lib.rs< / em > ,这样就不可能在 < em > tests< / em > 创建集成测试并使用 < code > extern crate< / code > 导入 < em > src/main.rs< / em > 中的函数了。这也是 Rust 二进制项目明确采用 < em > src/main.rs< / em > 调用 < em > src/lib.rs< / em > 中逻辑的结构的原因之一。通过这种结构,集成测试< strong > 就可以< / strong > 使用< code > extern crate< / code > 测试库 crate 中的主要功能,而如果这些功能没有问题的话,< em > src/main.rs< / em > 中的少量代码也就会正常工作且不需要测试。< / p >
< a class = "header" href = "#总结" name = "总结" > < h2 > 总结< / h2 > < / a >
< p > Rust 的测试功能提供了一个确保即使改变代码函数也能继续以指定方式运行的途径。单元测试独立的验证库的每一部分并能够测试私有实现细节。集成测试则涉及多个部分结合起来时能否使用,并像其他代码那样测试库的公有 API。Rust 的类型系统和所有权规则可以帮助避免一些 bug, 不过测试对于减少代码是否符合期望的逻辑 bug 是很重要的。< / p >
< p > 接下来让我们结合本章所学和其他之前章节的知识,在下一章一起编写一个项目!< / p >
< a class = "header" href = "#一个-io-项目" name = "一个-io-项目" > < h1 > 一个 I/O 项目< / h1 > < / a >
< blockquote >
< p > < a href = "https://github.com/rust-lang/book/blob/master/src/ch12-00-an-io-project.md" > ch12-00-an-io-project.md< / a >
< br >
commit efd59dd0fe8e3658563fb5fd289af9d862e07a03< / p >
< / blockquote >
< p > 之前几个章节我们学习了很多知识。让我们一起运用这些新知识来构建一个项目。在这个过程中,我们还将学习到更多 Rust 标准库的内容。< / p >
< p > 那么我们应该写点什么呢?这得是一个利用 Rust 优势的项目。Rust 的一个强大的用途是命令行工具: Rust 的运行速度、安全性、“单二进制文件”输出和跨平台支持使得它称为这类工作的绝佳选择。所以我们将创建一个我们自己的经典命令行工具:< code > grep< / code > 。< code > grep< / code > 有着极为简单的应用场景,它完成如下工作:< / p >
< ol >
< li > 它获取一个文件和一个字符串作为参数。< / li >
< li > 读取文件< / li >
< li > 寻找文件中包含字符串参数的行< / li >
< li > 打印出这些行< / li >
< / ol >
< p > 另外,我们还将添加一个额外的功能:一个环境变量允许我们大小写不敏感的搜索字符串参数。< / p >
< p > 还有另一个很好的理由使用< code > grep< / code > 作为示例项目: Rust 社区的成员, Andrew Gallant, 已经使用 Rust 创建了一个功能非常完整的< code > grep< / code > 版本。它叫做< code > ripgrep< / code > ,并且它非常非常快。这样虽然我们的< code > grep< / code > 将会非常简单,你也会掌握阅读现实生活中项目的基础知识。< / p >
< p > 这个项目将会结合之前所学的一些内容:< / p >
< ul >
< li > 代码组织(使用第七章学习的模块)< / li >
< li > vector 和字符串(第八章,集合)< / li >
< li > 错误处理(第九章)< / li >
< li > 合理的使用 trait 和生命周期(第十章)< / li >
< li > 测试(第十一章)< / li >
< / ul >
< p > 另外,我还会简要的讲到闭包、迭代器和 trait 对象, 他们分别会在第XX、YY和ZZ章详细介绍。< / p >
< p > 让我们一如既往的使用< code > cargo new< / code > 创建一个新项目:< / p >
< pre > < code class = "language-text" > $ cargo new --bin greprs
Created binary (application) `greprs` project
$ cd greprs
< / code > < / pre >
< p > 我们版本的< code > grep< / code > 的叫做“greprs”, 这样就不会迷惑用户让他们以为这就是可能已经在系统上安装了功能更完整的< code > grep< / code > 。< / p >
< a class = "header" href = "#接受命令行参数" name = "接受命令行参数" > < h2 > 接受命令行参数< / h2 > < / a >
< blockquote >
< p > < a href = "https://github.com/rust-lang/book/blob/master/src/ch12-01-accepting-command-line-arguments.md" > ch12-01-accepting-command-line-arguments.md< / a >
< br >
commit 2d32840aae46d247250310219e8c7169c7349017< / p >
< / blockquote >
< p > 第一个任务是让< code > greprs< / code > 接受两个命令行参数。crates.io 上有一些现存的库可以帮助我们,不过因为我们正在学习,我们将自己实现一个。< / p >
< p > 我们需要调用一个 Rust 标准库提供的函数:< code > std::env::args< / code > 。这个函数返回一个传递给程序的命令行参数的< strong > 迭代器< / strong > ( < em > iterator< / em > )。我们还未讨论到迭代器,第十三章会全面的介绍他们。但是对于我们的目的来说,使用他们并不需要知道多少技术细节。我们只需要明白两点:< / p >
< ol >
< li > 迭代器生成一系列的值。< / li >
< li > 在迭代器上调用< code > collect< / code > 方法可以将其生成的元素转换为一个 vector。< / li >
< / ol >
< p > 让我们试试列表 12-1 中的代码:< / p >
< figure >
< span class = "filename" > Filename: src/main.rs< / span >
< pre > < code class = "language-rust" > use std::env;
fn main() {
let args: Vec< String> = env::args().collect();
println!(" {:?}" , args);
}
< / code > < / pre >
< figcaption >
< p > Listing 12-1: Collect the command line arguments into a vector and print them out< / p >
< / figcaption >
< / figure >
<!-- Will add wingdings in libreoffice /Carol -->
< p > 首先使用< code > use< / code > 语句来将< code > std::env< / code > 模块引入作用域。当函数嵌套了多于一层模块时,比如说< code > std::env::args< / code > ,通常使用< code > use< / code > 将父模块引入作用域,而不是引入其本身。< code > env::args< / code > 比单独的< code > args< / code > 要明确一些。当然,如果使用了多余一个< code > std::env< / code > 中的函数,我们也只需要一个< code > use< / code > 语句。< / p >
< p > 在< code > main< / code > 函数的第一行,我们调用了< code > env::args< / code > ,并立即使用< code > collect< / code > 来创建了一个 vector。这里我们也显式的注明了< code > args< / code > 的类型:< code > collect< / code > 可以被用来创建很多类型的集合。Rust 并不能推断出我们需要什么类型,所以类型注解是必须的。在 Rust 中我们很少会需要注明类型,不过< code > collect< / code > 是就一个通常需要这么做的函数。< / p >
< p > 最后,我们使用调试格式< code > :?< / code > 打印出 vector。让我们尝试不用参数运行代码, 接着用两个参数: < / p >
< pre > < code > $ cargo run
[" target/debug/greprs" ]
$ cargo run needle haystack
...snip...
[" target/debug/greprs" , " needle" , " haystack" ]
< / code > < / pre >
< p > 你会注意一个有趣的事情:二进制文件的名字是第一个参数。其原因超出了本章介绍的范围< / p >
< / div >