返回引用的寿命不够长

Returning a reference does not live long enough

我刚开始学习 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 error: 'accounts' does not live long enough

这是从 MySQL 查询中获得一个结果的最佳方式,还是我一直在做完全错误的事情?

您不想return一个帐户的引用,但您希望在从数据库中检索后将所有权传递给调用者。

因此,将签名更改为:

fn load(db: &MyPool, id: i32) -> Account

现在的想法是 return 按值而不是引用对象:

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() 调用会使您的函数变得非常脆弱,因为任何失败都会使您的整个程序崩溃并引起恐慌。幸运的是,解决这种难闻气味的方法很简单:你想要 return Option<Account> 而不是 Account。然后删除对 unwrap() 的所有调用并让 Option<Account> 在整个调用中传播(您对 map() 的使用很好,因为它表示 "return None if you find None and return Some(f(a)) if you find Some(a)"。)