借来的价值活得不够久 [英] Borrowed value does not live long enough
问题描述
这是我的代码
extern crate postgres;
use postgres::{Connection, SslMode};
struct User {
reference: String,
email: String
}
static DB_URI: &'static str = "postgres://postgres:postgres@localhost/test";
fn main() {
let conn = Connection::connect(DB_URI, &SslMode::None).unwrap();
let trans = conn.transaction().unwrap();
let user = User {
reference: "123abc".to_string(),
email: "test@test.com".to_string()
};
let result = insert_user(&trans, &user);
trans.set_commit();
trans.finish();
}
fn insert_user<'_>(trans: &postgres::Transaction<'_>, user: &User) -> postgres::Result<postgres::rows::Rows<'_>> {
let query = "INSERT INTO usr (reference, email) VALUES ($1, $2)";
trans.prepare(query).unwrap().query(&[&user.reference, &user.email])
}
它产生了一个错误:
src/main.rs:31:2: 31:31 error: borrowed value does not live long enough
src/main.rs:31 trans.prepare(query).unwrap().query(&[&user.reference, &user.email])
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:29:114: 32:2 note: reference must be valid for the lifetime '_ as defined on the block at 29:113...
src/main.rs:29 fn insert_user<'_>(trans: &postgres::Transaction<'_>, user: &User) -> postgres::Result<postgres::rows::Rows<'_>> {
src/main.rs:30 let query = "INSERT INTO usr (reference, email) VALUES ($1, $2)";
src/main.rs:31 trans.prepare(query).unwrap().query(&[&user.reference, &user.email])
src/main.rs:32 }
src/main.rs:29:114: 32:2 note: ...but borrowed value is only valid for the block at 29:113
src/main.rs:29 fn insert_user<'_>(trans: &postgres::Transaction<'_>, user: &User) -> postgres::Result<postgres::rows::Rows<'_>> {
src/main.rs:30 let query = "INSERT INTO usr (reference, email) VALUES ($1, $2)";
src/main.rs:31 trans.prepare(query).unwrap().query(&[&user.reference, &user.email])
src/main.rs:32 }
error: aborting due to previous error
Could not compile `test`.
这里有什么问题?
推荐答案
我认为问题出在这里:
fn insert_user<'a>(trans: &postgres::Transaction<'a>, user: &User) -> postgres::Result<postgres::rows::Rows<'a>> {
(我已将生命周期参数名称更改为一些常用名称)
(I've changed the lifetime parameter name to some usual one)
在这里您声明结果中 Rows
参数中的生命周期应该与 Transaction
参数中的生命周期相同(本质上是 Connection
对象).但是,Rows
的生命周期参数等于 Statement
的生命周期,以及 Statement
值(通过调用 prepare()
方法)是一个局部变量,所以它严格小于要求(局部变量的生命周期总是小于参数中指定的生命周期).
Here you are stating that lifetime in Rows
parameter in the result should be the same as the lifetime in Transaction
parameter (which is essentially a lifetime of Connection
object). However, lifetime parameter of Rows
equals to the lifetime of a Statement
, and Statement
value (created by the call of prepare()
method) is a local variable, so it is strictly smaller than required (lifetimes of local variables are always smaller than lifetimes specified in parameters).
这个错误是合法的 - Rust 在这里防止了一个实际的逻辑错误.Rows
迭代器需要一个 Statement
来加载它的数据,但在这种情况下 Statement
被销毁,而 Rows
还活着.
This error is legitimate - Rust prevented an actual logic mistake here. Rows
iterator requires a Statement
to load its data, but in this case Statement
is destroyed while Rows
is still alive.
您需要做的是将 Rows
中的数据收集到某个容器(例如 Vec
)并返回.但是,insert_user()
似乎是一个不从数据库返回任何内容的查询.对于此类查询,您应该使用 <Statement
上的 code>execute() 方法,你的函数应该是这样的:
What you need to do is to collect the data from Rows
to some container (e.g. Vec
) and return it. However, insert_user()
seems to be a query which does not return anything from the database. For such queries you should use execute()
method on Statement
, and your function should look like this:
fn insert_user(trans: &postgres::Transaction, user: &User) -> postgres::Result<u64> {
let query = "INSERT INTO usr (reference, email) VALUES ($1, $2)";
trans.prepare(query).unwrap().execute(&[&user.reference, &user.email])
}
这篇关于借来的价值活得不够久的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!