[英]Returning mutable reference to an optional struct member
I want to make lazy connection to a Redis database. 我想与Redis数据库建立延迟连接。 I have a
Db
struct, which holds the Redis Client
. 我有一个
Db
结构,其中包含Redis Client
。 By default it is None
. 默认情况下为
None
。 Here is example code in Python: 这是Python中的示例代码:
import redis
class Db:
def __init__(self):
self.client = None
def get_client(self):
if self.client is None:
self.client = redis.StrictRedis(host='127.0.0.1')
return self.client
I tried this 我试过了
extern crate redis;
use redis::Client;
struct Db {
client: Option<Client>,
}
impl Db {
fn new() -> Db {
Db { client: None }
}
fn get_client(&mut self) -> Result<&Client, &'static str> {
if let Some(ref client) = self.client {
Ok(client)
} else {
let connection_string = "redis://127.0.0.1";
match Client::open(connection_string) {
Ok(client) => {
self.client = Some(client);
Ok(&self.client.unwrap())
}
Err(err) => Err("Error!"),
}
}
}
}
fn main() {
let mut db = Db::new();
db.get_client();
}
And I have compile errors. 而且我有编译错误。 I almost understand what compiler says, but I don't know how to solve the problem.
我几乎理解编译器的内容,但是我不知道如何解决该问题。
error: borrowed value does not live long enough
--> src/main.rs:28:29
|
28 | Ok(&self.client.unwrap())
| ^^^^^^^^^^^^^^^^^^^^ does not live long enough
29 | },
| - temporary value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the body at 19:66...
--> src/main.rs:19:67
|
19 | fn get_client(&mut self) -> Result<&Client, &'static str> {
| ^
error[E0507]: cannot move out of borrowed content
--> src/main.rs:28:29
|
28 | Ok(&self.client.unwrap())
| ^^^^ cannot move out of borrowed content
If you call unwrap()
you move T
out of the Option
. 如果调用
unwrap()
,则将T
移出Option
。 Since you only borrowed self
this leads to the cannot move out of borrowed content
error. 由于您仅借用
self
因此导致cannot move out of borrowed content
错误。
If you want to borrow the value inside an Option<T>
you can use the as_ref
method: 如果要在
Option<T>
借入值,则可以使用as_ref
方法:
extern crate redis;
use redis::Client;
struct Db {
client: Option<Client>,
}
impl Db {
fn new() -> Db {
Db { client: None }
}
fn get_client(&mut self) -> Result<&Client, &'static str> {
if let Some(ref client) = self.client {
Ok(client)
} else {
let connection_string = "redis://127.0.0.1";
match Client::open(connection_string) {
Ok(client) => {
self.client = Some(client);
Ok(self.client.as_ref().unwrap())
}
Err(_) => Err("Error!"),
}
}
}
}
fn main() {
let mut db = Db::new();
db.get_client().expect("get_client failed");
}
So, there is solution, to which I came 因此,我想到了解决方案
struct Db {
connection: Option<Connection>,
host: String,
port: u16,
db: u8,
}
impl Db {
fn new(host: String, port: u16, db: u8) -> Db {
Db {
host: host,
port: port,
db: db,
connection: None,
}
}
fn get_connection(&mut self) -> RedisResult<&Connection> {
if let Some(ref connection) = self.connection {
Ok(connection)
}
else {
let connection_string = format!("redis://{0}:{1}/{2}", self.host, self.port, self.db);
self.connection = Some(
Client::open(connection_string.as_ref())?.get_connection()?);
Ok(self.connection.as_ref().unwrap())
}
}
fn keys(&mut self) -> RedisResult<Vec<String>> {
let key_iter: redis::Iter<String> = self.get_connection()?.scan()?;
Ok(key_iter.collect())
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.