2017-01-13 1 views
0

Ich verwende , um eine HashMap in den Speicher zu behalten. Mit zwei Methoden füge ich hinzu und bekomme Elemente, aber ich habe einige Probleme mit den Lebenszeiten.Lifetime Problem mit einer lazy_static veränderbare Variable

Dies ist mein Code:

#[macro_use] 
extern crate lazy_static; 

use std::sync::Mutex; 
use std::collections::HashMap; 

lazy_static! { 
    static ref HASHMAP: Mutex<HashMap<String, Foo>> = Mutex::new({ 
     let mut m = HashMap::new(); 
     m.insert("one".to_string(), Foo{param1:"foo1".to_string(), param2:"foo2".to_string()}); 
     m.insert("two".to_string(), Foo{param1:"bar1".to_string(), param2:"bar2".to_string()}); 
     m 
    }); 
} 

pub struct Foo{ 
    param1: String, 
    param2: String, 
} 

pub fn ins_val(name: String, f: Foo){ 
    HASHMAP.lock().unwrap().insert(name, f); 
} 

pub fn get_val(k: &str) -> Option<&Foo>{ 
    HASHMAP.lock().unwrap().get(k) 
} 

Und das ist der Fehler:

HASHMAP.lock().unwrap().get(k) 
^^^^^^^^^^^^^^^^^^^^^^^ 
reference must be valid for the anonymous lifetime #1 defined on the block 

Antwort

9

Rust richtig hier einen Fehler verhindert.

Ihre get_val Funktion versucht, einen Verweis in HASHMAP zurückzugeben, aber das ist nicht sicher, es sei denn, Sie halten das Schloss weiter, da sonst jemand anders kommen und die Karte unter Ihren Füßen ändern könnte.

Sie müssen die Sperre entweder halten, bis Sie den Wert zurück (durch die Mutex Wache zusammen mit dem Wert der Rückkehr, zum Beispiel MutexGuardRef aus der owning_ref Kiste verwendet wird), oder den Wert zu kopieren, anstatt einen Verweis zurückzugeben:

pub fn get_val(k: &str) -> Option<Foo> { 
    HASHMAP.lock().unwrap().get(k).cloned() 
} 

Mit dieser Implementierung Foo müsste natürlich Clone implementieren.

+0

Eine andere Option besteht darin, die Schnittstelle so zu ändern, dass eine Schließung akzeptiert wird, die eine Referenz in die Karte aufnimmt, die wählen kann, ob eine Kopie der Referenz zurückgegeben oder nur untersucht werden soll. Weitere Details [in dieser Antwort] (http://stackoverflow.com/a/40853817/1600898). – user4815162342

+0

Beachten Sie, dass Sie 'option.cloned()' als Kurzform für 'option.map (Clone :: clone)' verwenden können. – user4815162342

+1

Danke - aktualisiert, um geklont zu verwenden. –

Verwandte Themen