我刚刚开始学习 Rust,并且主要来自 JavaScript 背景,所以当涉及到整个借用系统和内存管理时,我有点困惑。
我有以下代码:
fn load(db: &MyPool, id: i32) -> &Account{
let accounts: Vec<Account> = db.prepare("SELECT id, balance, name FROM `accounts` WHERE `id`=?")
.and_then(|mut stmt| {
stmt.execute(&[&id]).map(|result| {
result.map(|x| x.unwrap()).map(|row| {
Account{
id: from_value(&row[0]),
balance: from_value(&row[1]),
name: from_value(&row[2])
}
}).collect()
})
}).unwrap();
&accounts[0]
}
而且我已经设法修复了编译器抛出的所有错误
/main.rs:42:4: 42:12 错误:'accounts' 的生命周期不够长
这是从 MySQL 查询中获得一个结果的最佳方式,还是我的做法完全错误?
最佳答案
您不想返回对帐户的引用,但您希望在从数据库中检索后将所有权传递给调用者。
因此,将签名更改为:
fn load(db: &MyPool, id: i32) -> Account
现在的想法是按值而不是按引用返回对象:
accounts[0]
但是这样做会失败并返回 error: cannot move out of indexed content
.更好的方法是完全避免在向量中收集,并使用 Iterator::next(&self)
取第一个元素。这看起来像:
fn load(db: &MyPool, id: i32) -> Account{
let account: Account = db.prepare("SELECT id, balance, name FROM `accounts` WHERE `id`=?")
.and_then(|mut stmt| {
stmt.execute(&[&id]).map(|result| {
result.map(|x| x.unwrap()).map(|row| {
Account{
id: from_value(&row[0]),
balance: from_value(&row[1]),
name: from_value(&row[2])
}
}).next().unwrap() // <- next() takes the first elt of the iterator
})
}).unwrap();
account // <- return by value, pass ownership to caller
}
(未经测试,因为我无法重现您的开发环境。)
有点无关,但值得注意的是那些多个 unwrap()
调用会使你的函数变得非常脆弱,因为任何失败都会让你的整个程序崩溃。幸运的是,解决这种难闻气味的方法很简单:您想返回 Option<Account>
而不是 Account
.然后删除对 unwrap()
的所有调用并让 Option<Account>
在整个调用过程中传播(您使用 map()
很好,因为它表示“如果找到 None
则返回 None
,如果找到 Some(f(a))
则返回 Some(a)
”。)
关于mysql - 返回引用的生命周期不够长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31356518/