learn more rust-lang
繼續紀錄學習 Rust 的一些經驗
String vs str
在使用字串或者動態資料的時候,會需要思考要使用 String
還是 str
。其中的差別主要在於
同理:
str
是內部使用型態、跟 String 一樣永遠儲存一個合法的 UTF-8 字串、習慣上會使用
&str
來借用 (borrowed),使用 &'static str
就表示字串會直接存在執行檔內。
Trait
另一個有趣的設計是 rust 的 Trait 。在 rust 設計中 trait 定義了一個介面 (類似其他語言的 interface)、定義各種函數介面。
使用上,可以視為是函數的參數之一 pub fn notify(item: &impl Summary) { ... }
、也可以寫成
pub fn notify<T: Summary>(item: &T) { ... }
用作型態限制。而型態限制也可寫為
pub fn notify<T>(item: &T) where T: Summary { ... }
用 where 將型態限制放置函數後,
讓程式碼更加簡潔與減少雜訊。
同樣可以將 trait 當作是函數的回傳值。例如 fn returns_summarizable() -> impl Summary { ... }
回傳一個 trait 實作,但這樣的設計卻不能在一個函數,回傳兩種不同實作的 trait。
Dynamically Sized and Sized
在 rust 編譯中,需要知道變數的詳細細節、像是記憶體的使用量等。例如以下是一個有問題的程式碼:
x: str = "abc"
,在 rust 的世界中 x 的大小無法在編譯時間確定,因此才需要改用 &str
定義 x 的型態。因此針對 trait 而言,則需要使用 &dyn Trait
、Box<dyn Trait>
或者
Rc<dyn Trait>
定義,就可以在編譯時間得到記憶體的使用大小。
因此,當寫成 fn generic<T>(t: T) { ... }
的時候,其實是被視為 fn generic<T: Sized>(t: T){ ... }
。而實作上也可以主動寫成 fn generic<T: ?Sized>(t: T){ ... }
將型態 T 宣告為可能、可能沒有 Sized
Clone vs Copy
在 Rust 中 Clone 跟 Copy 都是代表複製的 trait,差別在於:
- Copy 是隱含 (implicit) 並且做位元操作的複製
- Clone 是明確
Box vs Rc vs Arc
在某些實作下會需要將物件存放在 Heap 、這時候 Rust 有提供多種選擇。最常見的情況使用 Box::new 將建立的物件放在 heap 下。
如果需要將這個記憶體物件分享給多個以上的擁有者 (ownership)、可以使用 Rc::new 或 Arc::new 。 差別是 Arc 保證 thread-safe、所以可以用在 multi-treading 的情境下。
- Box 適用在單一 ownershipt 的狀況
- Rc 適用在多個 ownershipt
- Arc 同 Rc、但保證 thread-safe
- Cell 提供內部可變 (interior mutability)、但只提供 Copy
- RefCell 一樣提供內部可變、但不受限於 Copy
- Mutex 跟 RwLock 同時提供互斥 (mutual-exclusion) 機制