模式匹配借用内容问题
pattern matching borrowed content issue
所以我有这段代码读取 input.csv
,在其中插入一列并将其写入 output.csv
extern crate csv;
use std::path::Path;
struct User {
reference: String,
email: String,
firstname: String,
lastname: String
}
fn main() {
let mut rdr = csv::Reader::from_file("/tmp/input.csv").unwrap().has_headers(false);
let mut wtr = csv::Writer::from_file(Path::new("/tmp/output.csv")).unwrap();
let users = get_users();
for record in rdr.decode() {
let rec: Option<Vec<String>> = match record {
Ok(rec) => Some(rec),
Err(e) => None
};
match rec {
Some(mut r) => {
let usr = users.iter().find(|&ur| ur.reference == r[27].to_string());
match usr {
Some(u) => r.insert(1, u.email),
None => r.insert(1, "Unknown".to_string())
}
wtr.write(r.iter());
}
None => {}
};
}
}
fn get_users() -> Vec<User> {
//retrieve users
}
它给我一个错误:
error: cannot move out of borrowed content
Some(u) => r.insert(1, u.email),
^
所以我知道它对 u.email
感到不安,因为 r
正试图获得它的所有权(?),但如何最好地处理这种情况?
这里是你的代码的一个稍微简化的部分,它演示了这个问题:
struct User {
reference: String,
email: String
}
let users = vec![
User { reference: "1".into(), email: "a@a.com".into() },
User { reference: "2".into(), email: "b@b.com".into() }
];
let records: Vec<Vec<String>> = vec![
vec!["1".into()],
vec!["2".into()],
vec!["3".into()]
];
for mut record in records {
let usr = users.iter().find(|ur| ur.reference == record[0]);
match usr {
Some(u) => record.insert(1, u.email),
None => record.insert(1, "Unknown".into())
}
// do whatever with record
}
usr
in let usr
这里是&User
类型,不是User
,因为iter()
returns满足[=17的迭代器=],因此 find()
returns Option<&User>
。因此,您不能从 u: &User
中取出 String
- 您不能从借用的引用中移出。顺便说一句,这是一个绝对正确的错误 - 如果允许这样做,您的代码将在多个记录对应同一用户的情况下中断(这将需要多次将电子邮件移出同一用户)。
这里最自然的方法就是使用 clone()
:
record.insert(1, u.email.clone())
它将创建包含在找到的 User
中的电子邮件字符串的副本,这正是您所需要的。
所以我有这段代码读取 input.csv
,在其中插入一列并将其写入 output.csv
extern crate csv;
use std::path::Path;
struct User {
reference: String,
email: String,
firstname: String,
lastname: String
}
fn main() {
let mut rdr = csv::Reader::from_file("/tmp/input.csv").unwrap().has_headers(false);
let mut wtr = csv::Writer::from_file(Path::new("/tmp/output.csv")).unwrap();
let users = get_users();
for record in rdr.decode() {
let rec: Option<Vec<String>> = match record {
Ok(rec) => Some(rec),
Err(e) => None
};
match rec {
Some(mut r) => {
let usr = users.iter().find(|&ur| ur.reference == r[27].to_string());
match usr {
Some(u) => r.insert(1, u.email),
None => r.insert(1, "Unknown".to_string())
}
wtr.write(r.iter());
}
None => {}
};
}
}
fn get_users() -> Vec<User> {
//retrieve users
}
它给我一个错误:
error: cannot move out of borrowed content
Some(u) => r.insert(1, u.email),
^
所以我知道它对 u.email
感到不安,因为 r
正试图获得它的所有权(?),但如何最好地处理这种情况?
这里是你的代码的一个稍微简化的部分,它演示了这个问题:
struct User {
reference: String,
email: String
}
let users = vec![
User { reference: "1".into(), email: "a@a.com".into() },
User { reference: "2".into(), email: "b@b.com".into() }
];
let records: Vec<Vec<String>> = vec![
vec!["1".into()],
vec!["2".into()],
vec!["3".into()]
];
for mut record in records {
let usr = users.iter().find(|ur| ur.reference == record[0]);
match usr {
Some(u) => record.insert(1, u.email),
None => record.insert(1, "Unknown".into())
}
// do whatever with record
}
usr
in let usr
这里是&User
类型,不是User
,因为iter()
returns满足[=17的迭代器=],因此 find()
returns Option<&User>
。因此,您不能从 u: &User
中取出 String
- 您不能从借用的引用中移出。顺便说一句,这是一个绝对正确的错误 - 如果允许这样做,您的代码将在多个记录对应同一用户的情况下中断(这将需要多次将电子邮件移出同一用户)。
这里最自然的方法就是使用 clone()
:
record.insert(1, u.email.clone())
它将创建包含在找到的 User
中的电子邮件字符串的副本,这正是您所需要的。