rust - 无法从函数返回命令行参数
问题描述
我正在尝试制作一个简单的函数来返回命令行参数。代码如下所示:
use std::env;
fn main() {
let (query, filename) = parse();
}
fn parse() -> (&str, &str) {
let args: Vec<String> = env::args().collect();
let query = args[1];
let filename = args[2];
return (query, filename)
}
但是它不会编译,错误如下所示:
error[E0106]: missing lifetime specifier
--> src/main.rs:15:22
|
15 | fn parse() -> (&str, &str) {
| ^ help: consider giving it a 'static lifetime: `&'static`
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
它建议我需要添加&'static
到函数声明中,如下所示:
fn parse() -> (&'static str, &'static str) {
但这也不起作用;
error[E0308]: mismatched types
--> src/main.rs:20:13
|
20 | return (query, filename)
| ^^^^^
| |
| expected reference, found struct `std::string::String`
| help: consider borrowing here: `&query`
|
= note: expected type `&'static str`
found type `std::string::String`
error[E0308]: mismatched types
--> src/main.rs:20:20
|
20 | return (query, filename)
| ^^^^^^^^
| |
| expected reference, found struct `std::string::String`
| help: consider borrowing here: `&filename`
|
= note: expected type `&'static str`
found type `std::string::String`
它说我需要添加借款,如下所示:
return (&query, &filename)
但这也不起作用;
warning: unused variable: `query`
--> src/main.rs:5:10
|
5 | let (query, filename) = parse();
| ^^^^^ help: consider prefixing with an underscore: `_query`
|
= note: #[warn(unused_variables)] on by default
warning: unused variable: `filename`
--> src/main.rs:5:17
|
5 | let (query, filename) = parse();
| ^^^^^^^^ help: consider prefixing with an underscore: `_filename`
error[E0507]: cannot move out of borrowed content
--> src/main.rs:17:17
|
17 | let query = args[1];
| ^^^^^^^
| |
| cannot move out of borrowed content
| help: consider borrowing here: `&args[1]`
error[E0507]: cannot move out of borrowed content
--> src/main.rs:18:20
|
18 | let filename = args[2];
| ^^^^^^^
| |
| cannot move out of borrowed content
| help: consider borrowing here: `&args[2]`
error[E0515]: cannot return value referencing local variable `filename`
--> src/main.rs:20:12
|
20 | return (&query, &filename)
| ^^^^^^^^^---------^
| | |
| | `filename` is borrowed here
| returns a value referencing data owned by the current function
error[E0515]: cannot return value referencing local variable `query`
--> src/main.rs:20:12
|
20 | return (&query, &filename)
| ^------^^^^^^^^^^^^
| ||
| |`query` is borrowed here
| returns a value referencing data owned by the current function
不知道发生了什么或为什么它不起作用,我也直接从教程中复制了示例。
解决方案
字符串很难生锈。首先,让我们回顾一下“什么是所有权?” , "The Slice Type"和"Lifetime Syntax"来自 Rust Book。
问题是 an&str
是一个对象的借用(由 表示&
)。rust 编译器需要知道它将被借用多长时间。现在,rust 实际上会尝试“生命周期省略”,假设返回值的生命周期将匹配输入值的生命周期,但在这种情况下没有输入值,因此无法推断。它需要你用生命周期来注释返回类型。您可以使用'static
,但您也可以为您的函数提供一个通用的生命周期说明符。这是一个简化的示例:
fn main() {
println!("{}", gimme_str());
}
fn gimme_str() -> &str {
return "foo";
}
那也不会编译。但是要编译它,您需要做的就是添加生命周期,如下所示:
fn main() {
println!("{}", gimme_str());
}
fn gimme_str<'a>() -> &'a str {
return "foo";
}
或者,您可以从输入中推断出生命周期,尽管在这种情况下这很奇怪,因为输入未使用:
fn main() {
println!("{}", gimme_str("bar"));
}
fn gimme_str(_input: &str) -> &str {
return "foo";
}
这就是生命周期说明符。但是您还有另一个问题,即您的返回值是函数拥有的字符串切片。我们可以通过修改之前的 rust playground 代码(带有生命周期说明符的代码)以简化的形式演示错误:
fn main() {
println!("{}", gimme_str());
}
fn gimme_str<'a>() -> &'a str {
let foo = String::from("foo");
return &foo;
}
借用总是借用某物。在前面的示例代码中,我使用了字符串文字,这&str
是对不可变字符串文字的借用。这是编译器生成的 rust 二进制文件的一部分,并且&str
可以只指向二进制文件的该部分。您可以将底层内存视为由二进制文件本身“拥有”,这意味着它永远不会超出范围(即字符串文字的生命周期是'static
)。
但是,在修改后的示例中,&foo
不是对字符串文字的借用,而是对String
对象的借用。该String
对象被分配给一个局部变量,因此它的所有者是该变量的所有者——函数。这意味着它将超出范围并在函数退出时被删除。但是一旦String
对象不再存在,借用它是无效的。
为了使String
超出函数范围,我们必须返回String
自身,以便将所有权转移给调用者。我们不能只是归还借款。见示例代码:
fn main() {
println!("{}", gimme_str());
}
fn gimme_str() -> String {
let foo = String::from("foo");
return foo;
}
要将其应用于您的案例,您将不得不String
从您的函数返回,而不是&str
.
推荐阅读
- excel - 使用 IFERROR 返回空白
- azure - 将 Salesforce 数据拉入 Azure
- .net-core - 基于导航属性的任何方法的通用表达式
- javascript - 如何向 Chromium 项目添加新的 API 扩展?
- android - 如何在 amplifyconfiguration.json 中配置访客凭据?
- django - 检查 Django 中是否存在具有 id 和 manytomany 字段的匹配对象
- php - 仅显示特定类别的分组产品
- scala - 从 Scala Circe 中的 Map 列表创建一个 json
- flutter - flutter 无法导入依赖项
- reactjs - 如何使用 VSCode 导航到 Functional React 中的子组件?