我有这些结构:
#[derive(Debug, RustcDecodable)]
struct Config {
ssl: Option<SslConfig>,
}
#[derive(Debug, RustcDecodable)]
struct SslConfig {
key: Option<String>,
cert: Option<String>,
}
Run Code Online (Sandbox Code Playgroud)
它们从toml文件中填充.这完全没问题.因为我得到了Option<T>它,我要么打电话unwrap()要么做match.
但如果我想做以下事情:
let cfg: Config = read_config(); // Reads a File, parses it and returns the Config-Struct
let keypath = cfg.ssl.unwrap().key.unwrap();
let certpath = cfg.ssl.unwrap().cert.unwrap();
Run Code Online (Sandbox Code Playgroud)
它将无法工作,因为cfg.ssl被移动到keypath.但它为什么会被感动?我叫unwrap()上ssl拿到钥匙(和unwrap()它).那么结果key.unwrap()应该被移动?
还是我错过了一点?什么是使这些结构可以像这样(或以其他整洁的方式)访问的最佳方法?我试图实现#[derive(Debug, RustcDecodable, Copy, Clone)],但是这是行不通的,因为我要实现Copy到String为好.然后,我要实现Copy对Vec<u8>等.必须有一个更方便的解决方案?
定义是Option::unwrap什么?从文档:
fn unwrap(self) -> T
Run Code Online (Sandbox Code Playgroud)
它消耗它的输入(cfg.ssl这里).
这是不是你想要的,你不是想从去Option<T>到&T由消费,这将启动&self(参考,并不值)...或者你想clone在Option之前调用unwrap.
克隆很少是解决方案......这里的替代方案是as_ref:
fn as_ref(&self) -> Option<&T>
Run Code Online (Sandbox Code Playgroud)
因此你可以写:
let keypath /*: &String*/ = cfg.ssl.as_ref().unwrap().key.as_ref().unwrap();
^~~~~~~ ^~~~~~~~
Run Code Online (Sandbox Code Playgroud)
所以结果
key.unwrap()应该被感动?
是的,但不仅如此。这里的关键见解是,变量 get 已移入 of unwrap()。让我们看看函数签名:
fn unwrap(self) -> T { ... }
Run Code Online (Sandbox Code Playgroud)
它需要self,所以对象被移动到函数中。但这也适用于ssl.unwrap()!
所以写的时候:
cfg.ssl.unwrap().key.unwrap();
Run Code Online (Sandbox Code Playgroud)
你先移动cfg.ssl到unwrap(),那么你访问结果的一个领域,该领域进入unwrap()试。所以是的,cfg.ssl被感动了。为了解决这个问题,您可以保存第一次unwrap()调用的临时结果,如下所示:
let ssl = cfg.ssl.unwrap();
let keypath = ssl.key.unwrap();
let certpath = ssl.cert.unwrap();
Run Code Online (Sandbox Code Playgroud)
或者您可以查看as_ref()方法,如果您不想移动(可能是这种情况)。