2017-04-04 22 views
2

我想與Redis數據庫進行惰性連接。我有一個Db結構,它包含Redis Client。默認情況下它是None。下面是示例代碼在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 

我想這

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(); 
} 

而且我有編譯錯誤。我幾乎明白編譯器說什麼,但我不知道如何解決這個問題。

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 

回答

2

如果你打電話給你unwrap()移動TOption的。既然你只借了self這導致了cannot move out of borrowed content錯誤。

如果你想借用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"); 
} 
+1

OP要求一個可變引用; 'as_ref'提供了一個不變的參考。我鼓勵你回答OP的*陳述問題,以便將來的搜索者可以得到答案。如果這不能回答OP的* actual *問題,那麼我也會解釋爲什麼它不需要在這種情況下是可變的。 – Shepmaster

+0

是的,你可以exaplain嗎? – sinitsynsv

1

因此,有解決方案,這是我來到

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()) 
    } 
}