一起學Rust-枚舉
- 2019 年 10 月 6 日
- 筆記


一、枚舉定義及使用
枚舉的定義在其他許多的語言中都有實現,舉例來說,比如C中的枚舉,枚舉值在未賦值的情況下默認從0開始遞增或從上一個枚舉值開始遞增,值類型可以是整數或字元類型,實質只能保存整型:
enum { A = 'd', //d 的 ascii碼值 B, //e 的 ascii碼值 C, //f 的 ascii碼值 D = 10, E, //11 };
Rust中的枚舉與C中的枚舉不同,功能非常強大,可以用枚舉表達更多的可能性數據。
看一下基本的枚舉定義:
//定了一個性別的枚舉 enum Gender { Male, Female, }
這裡面不同的是,Male和Female不是變數,而是枚舉值,而不像是C中會訪問到相應的數字。
#[derive(Debug)] enum Gender { Male, Female, } println!("{:?}, {:?}", Gender::Male, Gender::Female); ----- 輸出 ----- Male, Female
雖然輸出看上去是字元串類型,但實際是枚舉Gender類型
//這樣是編譯不通過的 if Gender::Male == "Male" {...}
枚舉值的代數形式是可以與實際的值進行結合的,而且是可以結合不同類型的數據,這使得枚舉的能力更強:
enum ErrorLevel { Error(String), Info(String, i32), Warning(String), }
每一個枚舉值可可以放入不同類型的數據,作為枚舉的一部分,那麼通過下面的例子看一下如何定義帶數據的枚舉值:
let info = ErrorLevel::Info("info error".to_string(), 3); match info { ErrorLevel::Info(k, v) => { println!("{}, {}", k, v); }, _ => () }
上面的例子裡面通過模式匹配獲取了Info枚舉值內的數據,這裡需要注意的是上面的例子在match程式碼塊後方就不能再使用info的變數了,這裡涉及到Rust中所有權的特性,也是Rust中非常重要的特性,這裡暫不過多的探討。
不過上面的例子僅支援固定類型的值,對於不同級別的錯誤日誌來說,有些時候會需要記錄一些不同類型的數據,所以可能需要不同的參數類型(這樣說稍微牽強),看下面枚舉結合 泛型 的例子:
enum ErrorLevel<T> { Error(T), Info(T), Warning(T), } let info = ErrorLevel::Info("abc"); //可以通過自動推斷類型 let info = ErrorLevel::<&str>::Info("abc"); //可以指定類型並賦值
三、內置常用枚舉
Option<T> 枚舉類型,通過IDE可以查看它的完整定義:
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] #[stable(feature = "rust1", since = "1.0.0")] pub enum Option<T> { /// No value #[stable(feature = "rust1", since = "1.0.0")] None, /// Some value `T` #[stable(feature = "rust1", since = "1.0.0")] Some(#[stable(feature = "rust1", since = "1.0.0")] T), }
簡化如下
enum Option<T> { None, Some(T) }
Option<T> 是一個非常重要的枚舉類型,在程式中無需引用庫,直接可以使用Some(T)和None。另外一個原因是因為Rust中去除了空類型,也就是沒有null、nil、none、這種在其他語言中非常常見的空類型,而是使用 Option<T> 作為存在值和空值間的選擇,因為 Option<T> 可以被賦予指定類型,即使當變數還為初始化時,也是明確變數應該被設置的類型。
let num:Option<i32> = None; //當變數暫不可知時,賦予None
上面的例子中,賦值為None時必須明確Option的類型,通過None是無法推斷Option中值的類型的。
在上一期的《一起學Rust-實戰leetcode(一)》中使用到的HashMap,其get方法獲取到的就是一個Option<T>枚舉類型,存在則返回Some包含的值,哈希中不存在則返回None。
Result<T,E> 枚舉類型,僅有兩個枚舉值:
enum Result<T, E> { Ok(T), //成功情況 Err(E) //失敗情況 }
在這個枚舉用的比較廣泛,例如 Tcp連接的創建、文件讀取、標準輸入等,會存在成功或異常的情況,所以通過枚舉類型攜帶成功或錯誤的資訊返回。
fn main() { let mut input = String::new(); // if let Ok(string_bytes) = stdin().read_line(&mut input) { // println!("{}, {}", string_bytes, input); // } else { // println!("error"); // } //這裡寫法上方的寫法意義是一樣的, let res = stdin().read_line(&mut input); match res { Ok(v) => println!("{}, {}", v, input), Err(e) => println!("{}", e) } }
枚舉類型就介紹到這裡,要想快速掌握還是應該多多練習~
覺得還不錯的話就關注下吧
完
