5 個非常有用的 Rust 小技巧
自從做了https://github.com/chainx-org/ChainX
專案以後,主力語言就轉到了 Rust,今天剛好這個文章,比較剪短,跟大家分享一下。
在開始之前,跟大家簡單介紹 ChainX 專案。ChainX 是一個基於substrate 專注於區塊鏈資產跨鏈專案,目前已經實現了 BTC 跨鏈, 可以在我們的測試網進行充值體驗,如何參與測試網請點選這裡 。
我們將會在最近上線主網,並進行開源,歡迎有識之士進行關注,專案地址是:https://github.com/chainx-org/ChainX
。此外,也歡迎開發者加入我們的開發群,有興趣的可以私信我加群。
ChainX 也在不斷招人,運營,技術都招,如果有任何想法,歡迎與我聯絡,期待大牛加入!
好了,開始今天的“正題”:
更“護眼”的 print 除錯
當我們用 print 大法進行除錯的時候,經常會用到:?
格式化操作符。但是除此以外,還有另外一些非常好用的操作符!另一個非常有用的就是:#?
,它會自動加入換行和縮排來增強輸出的可讀性。
#[derive(Debug)] struct Foo { x: i32, y: i32, } let foo = Foo { x: 1, y: 2 }; println!("Simple debug:\n{:?}", foo); println!("Pretty debug:\n{:#?}", foo);
Simple debug: Foo { x: 1, y: 2 } Pretty debug: Foo { x: 1, y: 2, }
關於除錯,還可以瞭解一下最近新家的dbg!
巨集https://doc.rust-lang.org/std/macro.dbg.html
。
unimplemented!
有時候,你可能會想要一個不用進行完整實現的函式。比如,你可能想要一些方法的測試,又或者你想要為以後的開發保留某個 feature,這時unimplemented!
就會派上用場。如果想要的型別是什麼,unimplemented!
都會被展開為能夠編譯的表示式。
enum VerySimpleList<T> { Empty, Elem(T, Box<VerySimpleList>), } impl<T> VerySimpleList<T> { fn len(&self) -> usize { match self { VerySimpleList::Empty => 0, VerySimpleList::Elem(..) => unimplemented!(), } } }
..
結構體字面操作符
有時候,你想要部分地複製一個結構體,也就是裡面有部分欄位不一樣,但是其他欄位保留複製結構體裡面的內容。儘管你可以通過手動 clone 然後進行修改,但是還有更簡單的方式!通過..
操作符後面跟著這個結構體的另一個例項,剩下的欄位就會用後面這個例項的欄位填充。此外,它並不要求結構體實現Clone
約束。
#[derive(Debug, Default)] struct Foo { x: i32, y: i32, } let a = Foo { x: 1, y: 2 }; let b = Foo { x: 2, ..a }; let c = Foo { x: 2, ..Default::default() };
模式匹配 guard
有時當使用模式匹配時,你所匹配的模式並沒有跟你想要處理的格式完美匹配。比如,你可能會寫這樣的程式碼:
fn divide_opt(x: Option<i32>, y: Option<i32>) -> Option<i32> { match (x, y) { (Some(i), Some(0)) => None (Some(i), Some(j)) => Some(i / j) _ => None, } }
你大可以把這兩種情況組合起來:
fn divide_opt(x: Option<i32>, y: Option<i32>) -> Option<i32> { match (x, y) { (Some(i), Some(j)) => { if j == 0 { None } else { Some(i / j) } } _ => None, } }
但是,還有更好的方式!模式後面可以跟著一個條件表示式,叫做 “guard":
fn divide_opt(x: Option<i32>, y: Option<i32>) -> Option<i32> { match (x, y) { (Some(i), Some(j)) if j != 0 => Some(i / j), _ => None, } }
填充格式操作符
想要在 Rust 裡面進行左側填充字元?不需要任何額外的包就可以實現!只要用:>
操作符後面跟上一個長度,然後就好了!
let score1 = 100; let score2 = 1000; let score3 = 10000; println!("{:>5}", score1); println!("{:>5}", score2); println!("{:>5}", score3);
這會打印出:
first player:padded! second player: padded! third player:padded!
等一下,還沒完!如果你想要兩邊填充,也有辦法,:^
後面跟上填充後的字串寬度就行了:
let padded = "padded"; println!("[{:^10}]", padded)
這會打印出:
[padded]
你知道還可以用不同的字元進行填充嗎?只要在箭頭前面指定填充字元就行了!
let title = "SCORES"; let player1 = "first player:"; let player2 = "second player:"; let player3 = "third player:"; let score1 = 100; let score2 = 1000; let score3 = 10000; println!("{:_^20}", title); println!("{:<14} {:>5}", player1, score1); println!("{:<14} {:>5}", player2, score2); println!("{:<14} {:>5}", player3, score3);
這會打印出:
_______SCORES_______ first player:100 second player:1000 third player:10000