視頻地址
頭條地址:https://www.ixigua.com/i6765442674582356483
B站地址:https://www.bilibili.com/video/av78062009?p=1
網易雲課堂地址:https://study.163.com/course/introduction.htm?courseId=1209596906#/courseDetail?tab=1
github地址
介紹
Option類型代表了一個可選的值,每個Option要麼是一個Some中包含一個值,要麼是一個None。Option的定義如下:
pub enum Option<T> {
None,
Some(T),
}
用法
Option主要有以下一些用法:
-
初始化值;
-
作爲在整個輸入範圍內沒有定義的函數的返回值;
-
作爲返回值,用
None
表示出現的簡單錯誤; -
作爲結構體的可選字段;
-
作爲結構體中可借出或者是可載入的字段;
-
作爲函數的可選參數;
-
代表空指針;
-
用作複雜情況的返回值。
此處,我們舉例說明一下“作爲結構體可借出或者是可載入的字段”。
use std::thread;
use std::time::Duration;
struct Worker {
thread: thread::JoinHandle<()>,
}
impl Worker {
fn new() -> Worker {
let thread = thread::spawn(move || {
println!("start sleep 10 secs ...");
thread::sleep(Duration::from_secs(10));
});
Worker {
thread: thread,
}
}
}
struct ThreadPool {
workers: Vec<Worker>,
}
impl ThreadPool {
fn new(size: usize) -> ThreadPool {
assert!(size > 0);
let mut workers = Vec::with_capacity(size);
for _ in 0..size {
workers.push(Worker::new());
}
ThreadPool { workers }
}
}
impl Drop for ThreadPool {
fn drop(&mut self) {
for worker in &mut self.workers {
worker.thread.join().unwrap();//報錯,無法編譯,thread也無法實現copy trait
println!("worker thread finished!");
}
}
}
fn main() {
let _pool = ThreadPool::new(3);
println!("Hello, world!");
}
上述例子中,實現了一個不完整的線程池,在Worker中,有一個字段爲線程的句柄。當線程池對象drop時,無法使用mut對象中成員的引用(即通過&mut self.workers取出worker,在調用worker.thread.join())。爲了解決此問題,我們可以將Worker結構體修改如下:
struct Worker {
// thread: thread::JoinHandle<()>,
thread: Option<thread::JoinHandle<()>>,
}
完整代碼爲:
use std::thread;
use std::time::Duration;
struct Worker {
// thread: thread::JoinHandle<()>,
thread: Option<thread::JoinHandle<()>>,
}
impl Worker {
fn new() -> Worker {
let thread = thread::spawn(move || {
println!("start sleep 10 secs ...");
thread::sleep(Duration::from_secs(10));
});
Worker {
// thread: thread,
thread: Some(thread),
}
}
}
struct ThreadPool {
workers: Vec<Worker>,
}
impl ThreadPool {
fn new(size: usize) -> ThreadPool {
assert!(size > 0);
let mut workers = Vec::with_capacity(size);
for _ in 0..size {
workers.push(Worker::new());
}
ThreadPool { workers }
}
}
impl Drop for ThreadPool {
fn drop(&mut self) {
for worker in &mut self.workers {
// worker.thread.join().unwrap();
// println!("worker thread finished!");
if let Some(thread) = worker.thread.take() {//此處將thread從Worker的thread字段的Option中拿出來,使用了“Option類型作爲結構體中可借出或者是可載入的字段”
thread.join().unwrap();
println!("worker thread finished!");
}
}
}
}
fn main() {
let _pool = ThreadPool::new(3);
println!("Hello, world!");
}
在ThreadPool的drop實現中,通過option的take方法,將thread從worker中移出,然後調用join,成功解決問題。
方法
-
is_some
pub fn is_some(&self) -> bool
當Option中有值時,返回true。
-
is_none
pub fn is_none(&self) -> bool
當Option爲None時,返回true。
-
contains
pub fn contains<U>(&self, x: &U) -> bool where U: PartialEq<T>,
當Some中包含給定的值時,返回true。這個是nightly API。
//示例 #![feature(option_result_contains)] let x: Option<u32> = Some(2); assert_eq!(x.contains(&2), true); let x: Option<u32> = Some(3); assert_eq!(x.contains(&2), false);
-
as_ref
pub fn as_ref(&self) -> Option<&T>
將
&Option<T>
轉換爲Option<&T>
//例子 let text: Option<String> = Some("Hello, world!".to_string()); let text_length: Option<usize> = text.as_ref().map(|s| s.len()); println!("still can print text: {:?}", text);
-
take
pub fn take(&mut self) -> Option<T>
把值從Option中拿出來,留下None。
let mut x = Some(2); let y = x.take(); assert_eq!(x, None); assert_eq!(y, Some(2)); let mut x: Option<u32> = None; let y = x.take(); assert_eq!(x, None); assert_eq!(y, None);
-
copied
pub fn copied(self) -> Option<T>
從
Option<&T>
得到Option<T>
(通過複製來實現)let x = 12; let opt_x = Some(&x); assert_eq!(opt_x, Some(&12)); let copied = opt_x.copied(); assert_eq!(copied, Some(12));
-
cloned
pub fn cloned(self) -> Option<T>
從
Option<&T>
得到Option<T>
(通過克隆來實現)let x = 12; let opt_x = Some(&x); assert_eq!(opt_x, Some(&12)); let cloned = opt_x.cloned(); assert_eq!(cloned, Some(12));