Cow
Cow 是一種非常方便的列舉。它的意思是"寫時克隆",如果你不需要 String
,可以回傳 &str
,如果你需要就回傳 String
。(它也可以對陣列與向量等等做同樣的處理)。
為了理解它,我們看一下簽名。它說:
pub enum Cow<'a, B> where B: 'a + ToOwned + ?Sized, { Borrowed(&'a B), Owned(<B as ToOwned>::Owned), } fn main() {}
你馬上就知道,'a
意味著它可以和參考一起用。ToOwned
特徵意味著它是個可以轉換成具有擁有權的型別。例如,str
通常是參考(&str
),你可以把它轉換成具有擁有權的 String
。
接下來是 ?Sized
。這意味著"也許是 Sized,但也許不是"。Rust 中幾乎每個型別都是 Sized 的,但像 str
這樣的型別卻不是。這就是為什麼我們需要附帶 &
給 str
,因為編譯器不知道大小。所以如果你想要可以用像是 str
的特徵,你可以加上 ?Sized
。
接下來是 enum
的變體。它們是 Borrowed
和 Owned
。
想像你有個回傳 Cow<'static, str>
的函式。如果你告訴函式回傳 "My message".into()
,它就會檢視型別:"My message"是 str
。這是個 Borrowed
型別,所以它選擇 Borrowed(&'a B)
。那它就變成了 Cow::Borrowed(&'static str)
。
而如果你給它 format!("{}", "My message").into()
,那麼它就會檢視型別。這次是個 String
,因為 format!
做出 String
。那這次就會選擇 "Owned"。
這是個測試 Cow
的範例。我們將把數字放入會回傳 Cow<'static, str>
的函式中。根據這個數字,它會建立 &str
或 String
。然後用 .into()
將其變成 Cow
。這樣做的時候,它就會選擇 Cow::Borrowed
或者 Cow::Owned
其中之一。那我們就匹配看看它選的是哪一個。
use std::borrow::Cow; fn modulo_3(input: u8) -> Cow<'static, str> { match input % 3 { 0 => "Remainder is 0".into(), 1 => "Remainder is 1".into(), remainder => format!("Remainder is {}", remainder).into(), } } fn main() { for number in 1..=6 { match modulo_3(number) { Cow::Borrowed(message) => println!("{} went in. The Cow is borrowed with this message: {}", number, message), Cow::Owned(message) => println!("{} went in. The Cow is owned with this message: {}", number, message), } } }
印出:
1 went in. The Cow is borrowed with this message: Remainder is 1
2 went in. The Cow is owned with this message: Remainder is 2
3 went in. The Cow is borrowed with this message: Remainder is 0
4 went in. The Cow is borrowed with this message: Remainder is 1
5 went in. The Cow is owned with this message: Remainder is 2
6 went in. The Cow is borrowed with this message: Remainder is 0
Cow
還有一些其他方法,像是 into_owned
或者 into_borrowed
,如果你需要就可以改變它。