头条地址: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 {
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,
}
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,
}
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(&self, x: &U) -> bool
where
U: PartialEq,
当Some中包含给定的值时,返回true。这个是nightly API。
//示例
#![feature(option_result_contains)]
let x: Option = Some(2);
assert_eq!(x.contains(&2), true);
let x: Option = Some(3);
assert_eq!(x.contains(&2), false);
as_ref
pub fn as_ref(&self) -> Option
将&Option
转换为Option
//例子
let text: Option = Some("Hello, world!".to_string());
let text_length: Option = text.as_ref().map(|s| s.len());
println!("still can print text: {:?}", text);
take
pub fn take(&mut self) -> Option
把值从Option中拿出来,留下None。
let mut x = Some(2);
let y = x.take();
assert_eq!(x, None);
assert_eq!(y, Some(2));
let mut x: Option = None;
let y = x.take();
assert_eq!(x, None);
assert_eq!(y, None);
copied
pub fn copied(self) -> Option
从Option
得到Option
(通过复制来实现)
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
从Option
得到Option
(通过克隆来实现)
let x = 12;
let opt_x = Some(&x);
assert_eq!(opt_x, Some(&12));
let cloned = opt_x.cloned();
assert_eq!(cloned, Some(12));