Rust編寫自動化測試實(shí)例權(quán)威指南
一. 簡述
雖然Rust
的類型系統(tǒng)為我們提供了相當(dāng)多的安全保障,但是還是不足以防止所有的錯誤。因此,Rust
在語言層面內(nèi)置了編寫測試代碼、執(zhí)行自動化測試任務(wù)的功能。
測試是一門復(fù)雜的技術(shù),本章覆蓋關(guān)于如何編寫優(yōu)秀測試的每一個細(xì)節(jié),但是會討論Rust
測試工具的運(yùn)行機(jī)制。我們會向你介紹編寫測試時常用的標(biāo)注和宏、運(yùn)行測試的默認(rèn)行為和選項(xiàng)參數(shù),以及如何將測試用例組織為單元測試與集成測試。
二. 編寫測試
Rust
語言中的測試時一個函數(shù),它被用于驗(yàn)證非測試代碼是否按照期望的方式運(yùn)行。測試函數(shù)的函數(shù)體中一般包含3個部分:
- 準(zhǔn)備所需的數(shù)據(jù)或狀態(tài)
- 調(diào)用需要測試的代碼
- 斷言運(yùn)行結(jié)果與我們期望的一致
接下來,我們會一起學(xué)習(xí)用于編寫測試代碼的相關(guān)功能,它們包含test
屬性、一些測試宏及should_panic
屬性。此時我們將建一個庫項(xiàng)目:cargo new adder —lib
此時adder
庫項(xiàng)目自動生成一個src/lib.rs
文件,此時cargo會給我們創(chuàng)建一個簡單的測試代碼模塊:
pub fn add(left: usize, right: usize) -> usize { left + right } #[cfg(test)] mod tests { use super::*; #[test] // @1 fn it_works() { let result = add(2, 2); assert_eq!(result, 4); // @2 } }
我們可以看到@1
這一行的#[test]
標(biāo)注:它將當(dāng)前的函數(shù)標(biāo)記為一個測試,并使該函數(shù)可以在測試運(yùn)行中被識別出來。要知道,即便是在tests
模塊中也可能會存在普通的非測試函數(shù),它們通常被用來執(zhí)行初始化操作或一些常用指令,所以我們必須要將測試函數(shù)標(biāo)注為#[test]
。函數(shù)體中@2
使用了assert_eq!
宏斷言,這是一個典型的測試用例編寫方式。這時我們執(zhí)行命令:cargo test
xxxxx@xxxxxx adder % cargo test Compiling adder v0.1.0 (/rust-example/adder) Finished test [unoptimized + debuginfo] target(s) in 0.05s Running unittests src/lib.rs (target/debug/deps/adder-96bda0c2404f749c) running 1 test // 正在執(zhí)行一個測試 test tests::it_works ... ok // 此時函數(shù) test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s // 測試摘要,表示該集合中的所有測試均成功通過,1 passed; 0 failed則統(tǒng)計(jì)了通過和失敗的測試總數(shù) Doc-tests adder // 文件測試的結(jié)果 running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
此時我們刪除初始化的代碼,我們編寫下面兩個測試函數(shù):
extern crate core; #[cfg(test)] mod tests { use super::*; #[test] fn ok_test() { assert_eq!(2 + 2, 4); } #[test] fn fail_test() { panic!("Make this test fail"); } }
此時我們再次執(zhí)行cargo test
運(yùn)行測試!可預(yù)見的ok_test
肯定是OK
的,fail_test
我們在里面寫了panic!
測試失??!
xxxxxx@xxxxxx adder % cargo test Compiling adder v0.1.0 (/rust-example/adder) Finished test [unoptimized + debuginfo] target(s) in 0.13s Running unittests src/lib.rs (target/debug/deps/adder-96bda0c2404f749c) running 2 tests test tests::ok_test ... ok test tests::fail_test ... FAILED failures: ---- tests::fail_test stdout ---- thread 'tests::fail_test' panicked at 'Make this test fail', src/lib.rs:11:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace failures: tests::fail_test test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s error: test failed, to rerun pass `--lib`
測試信息輸出非常明顯,測試失敗的位置提示很明確。
三. 測試相關(guān)的宏和函數(shù)
下面我們介紹一些我們在編寫測試時會使用到的相關(guān)宏和方法!
3.1. 使用assert!宏檢查結(jié)果
assert!
宏由標(biāo)準(zhǔn)庫提供,它可以確保測試中某些條件的值是true
。assert!
宏可以接收一個能夠被計(jì)算為布爾類型的值作為參數(shù)。當(dāng)這個值為true
時,assert!
宏什么都不做并正常通過測試。而當(dāng)值時false
時,assert!
宏就會調(diào)用panic!
宏,進(jìn)而導(dǎo)致測試失敗。使用assert!
宏可以檢查代碼是否按照我們預(yù)期的方式運(yùn)行。
#[derive(Debug)] pub struct Rectangle { length: u32, width: u32, } impl Rectangle { pub fn can_hold(&self, other: &Rectangle) -> bool { self.length > other.length && self.width > other.width } } #[cfg(test)] mod tests { use super::*; #[test] fn larger_can_hold_smaller() { let larger = Rectangle { length: 9, width: 7 }; let smaller = Rectangle { length: 5, width: 1 }; assert!(larger.can_hold(&smaller)); } #[test] fn smaller_cannot_hold_larger() { let larger = Rectangle { length: 9, width: 7 }; let smaller = Rectangle { length: 5, width: 1 }; assert!(smaller.can_hold(&larger)); // fasle, 斷言失敗 } }
此時執(zhí)行cargo test
測試代碼:一個成功,一個失敗。
xxxxx@xxxxxxx adder % cargo test Compiling adder v0.1.0 (/rust-example/adder) Finished test [unoptimized + debuginfo] target(s) in 0.12s Running unittests src/lib.rs (target/debug/deps/adder-96bda0c2404f749c) running 2 tests test tests::larger_can_hold_smaller ... ok test tests::smaller_cannot_hold_larger ... FAILED failures: ---- tests::smaller_cannot_hold_larger stdout ---- thread 'tests::smaller_cannot_hold_larger' panicked at 'assertion failed: smaller.can_hold(&larger)', src/lib.rs:29:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace failures: tests::smaller_cannot_hold_larger test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s error: test failed, to rerun pass `--lib`
3.2. 使用assert_eq!宏和assert_ne!宏判斷相等性
在對功能進(jìn)行測試時,我們常常需要將被測試代碼的結(jié)果與我們所期望的結(jié)果相比較,并檢查它們是否相等。在標(biāo)準(zhǔn)庫中提供了一對可以簡化編程的宏:assert_eq!
和assert_ne!
。這兩個宏分別用于比較并斷言兩個參數(shù)相等或不相等。在斷言失敗時,它們還可以自動打印出兩個參數(shù)的值,從而方便我們觀察測試失敗的原因;相反,使用assert!
宏則只能得知==
判斷表達(dá)式失敗的事實(shí),而無法知曉用于比較的值。
pub fn add_two(a: i32) -> i32 { a + 2 } #[cfg(test)] mod tests { use super::*; #[test] fn ok_adds_two_eq() { // 斷言結(jié)果相同測試通過 assert_eq!(4, add_two(2)); } #[test] fn fail_adds_two_eq() { // 斷言結(jié)果不相同觸發(fā)panic assert_eq!(5, add_two(2)); } #[test] fn ok_adds_two_ne() { // 斷言結(jié)果不一致測試通過 assert_ne!(5, add_two(2)); } #[test] fn fail_adds_two_ne() { // 斷言結(jié)果相同觸發(fā)panic assert_ne!(4, add_two(2)); } }
執(zhí)行測試代碼:
yuelong@yuelongdeMBP adder % cargo test Compiling adder v0.1.0 (/Users/yuelong/CodeHome/TestProject/rust-example/adder) Finished test [unoptimized + debuginfo] target(s) in 0.12s Running unittests src/lib.rs (target/debug/deps/adder-96bda0c2404f749c) running 4 tests test tests::ok_adds_two_ne ... ok test tests::ok_adds_two_eq ... ok test tests::fail_adds_two_eq ... FAILED test tests::fail_adds_two_ne ... FAILED failures: ---- tests::fail_adds_two_eq stdout ---- thread 'tests::fail_adds_two_eq' panicked at 'assertion failed: `(left == right)` left: `5`, right: `4`', src/lib.rs:16:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ---- tests::fail_adds_two_ne stdout ---- thread 'tests::fail_adds_two_ne' panicked at 'assertion failed: `(left != right)` left: `4`, right: `4`', src/lib.rs:26:9 failures: tests::fail_adds_two_eq tests::fail_adds_two_ne test result: FAILED. 2 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s error: test failed, to rerun pass `--lib`
測試順利通過檢查。
3.3. 添加自定義的錯誤提示信息
我們也可以添加自定義的錯誤提示信息,將其作為可選的參數(shù)傳入assert!
、assert_eq!
和assert_ne!
宏。實(shí)際上面任何在assert!
、assert_eq!
和assert_ne!
的必要參數(shù)之后出現(xiàn)的參數(shù)都會一起被傳遞給format!
宏。因此,你甚至可以將一個包含{}
占位符的格式化字符串及相對應(yīng)的填充值作為參數(shù)一起傳遞給這個宏。自定義的錯誤提示信息可以很方便地記錄當(dāng)前斷言的含義;這樣在測試失敗時,我們就可以更容易的知道代碼到底出了什么問題。
pub fn greeting(name: &str) -> String { String::from("Hello!") } #[cfg(test)] mod tests { use super::*; #[test] fn greeting_test() { let result = greeting("Carol"); assert!( result.contains("Carol"), "Greeting did not contain name, value was `{}`", result ) } }
當(dāng)測試失敗之后:
running 1 test test tests::greeting_test ... FAILED failures: ---- tests::greeting_test stdout ---- thread 'tests::greeting_test' panicked at 'Greeting did not contain name, value was `Hello!`', src/lib.rs:16:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace failures: tests::greeting_test test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
這次的測試輸出中包含了實(shí)際的值,他能幫助我們觀察程序真正發(fā)生的行為,并迅速定位與預(yù)期產(chǎn)生差異的地方。
3.4. 使用should_panic檢查paninc
除了檢查代碼是否返回了正確的結(jié)果,確認(rèn)代碼能否按照預(yù)期處理錯誤狀態(tài)同樣重要。
pub struct Guess { value: u32, } impl Guess { pub fn new(value: u32) -> Guess { if value < 1 || value > 100 { panic!("Guess value must be between 1 and 100, got {}.", value); } Guess { value } } pub fn new_plus(value: u32) -> Guess { if value < 1 { panic!("Guess value must be between 1 and 100, got {}.", value); } Guess { value } } } #[cfg(test)] mod tests { use super::*; #[test] #[should_panic] fn new_test() { // 此時肯定會發(fā)生錯誤, 但是因?yàn)榧恿藄hould_panic宏,所有測試通過 Guess::new(200); } #[test] #[should_panic] fn new_plus_test() { // 此時不會發(fā)生錯誤, 但是因?yàn)榧恿藄hould_panic宏,所有測試無法通過 Guess::new(200); } }
執(zhí)行cargo test
并不會失敗:
running 2 tests test tests::new_plus_test - should panic ... FAILED test tests::new_test - should panic ... ok failures: ---- tests::new_plus_test stdout ---- note: test did not panic as expected failures: tests::new_plus_test test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
使用should_panic
進(jìn)行的測試可能會有些模糊不清,因?yàn)樗麄儍H僅能夠說明被檢查的代碼會發(fā)生panic
。即便函數(shù)發(fā)生panic
的原因和我們預(yù)期的不同,使用should_panic
進(jìn)行測試也會順利通過。為了讓should_panic
測試更加精確一些,我們可以在should_panic
屬性中添加可選參數(shù)expected
。它會檢查panic
發(fā)生時輸出的錯誤提示信息是否包含了指定的文字。例子:
pub struct Guess { value: u32, } impl Guess { pub fn new(value: u32) -> Guess { if value < 1 { panic!("Guess value must be greater than or equal to 1, got {}.", value); } else if value > 100 { panic!("Guess value must be less than or equal to 100, got {}.", value); } else { Guess { value } } } } #[cfg(test)] mod tests { use super::*; #[test] #[should_panic(expected = "Guess value must be less than or equal to 100")] fn new_test() { // 此時肯定會發(fā)生錯誤 Guess::new(0); } }
此時再次執(zhí)行測試:
running 1 test test tests::new_test - should panic ... FAILED failures: ---- tests::new_test stdout ---- thread 'tests::new_test' panicked at 'Guess value must be greater than or equal to 1, got 0.', src/lib.rs:8:13 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace note: panic did not contain expected string panic message: `"Guess value must be greater than or equal to 1, got 0."`, expected substring: `"Guess value must be less than or equal to 100"` failures: tests::new_test test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
3.5. 使用Result<T, E>編寫測試
到目前為止,我們編寫的測試都會在運(yùn)行失敗時觸發(fā)panic。不過我們也可以用Result<T, E>來編寫測試!例子:
#[cfg(test)] mod tests { use super::*; #[test] fn new_test() -> Result<(), String> { if 2 + 2 == 4 { Ok(()) } else { Err(String::from("two plus two does not equal four")) } } }
在函數(shù)體中,我們不再調(diào)用assert_eq!
宏,而是在測試的時候通過時返回Ok(())
,在失敗時返回一個帶有String
的Err
值。
不要在使用Reuslt<T, E>編寫的測試上標(biāo)注#[should_panic]。在測試失敗時,我們應(yīng)該直接返回一個Err值。
四. 控制測試的運(yùn)行方式
如同cargo run
會編譯代碼并運(yùn)行生成的二進(jìn)制文件一樣,cargo test
同樣會在測試環(huán)境下編譯代碼,并運(yùn)行生成的測試二進(jìn)制文件。你可以通過指定命令行參數(shù)來改變cargo test
的默認(rèn)行為。
cargo test --help // 查看cargo test的可用參數(shù) cargo test -- --help // 顯示出所有可用在 -- 之后的參數(shù)
4.1. 并行或串行的進(jìn)行測試
當(dāng)我們嘗試運(yùn)行多個測試,Rust會默認(rèn)使用多線程來執(zhí)行它們。這樣可以讓測試更快地運(yùn)行完畢。從來盡早得到代碼是否可以正常工作的反饋。但是由于測試是同時進(jìn)行的,所以開發(fā)者必須保證測試之間不會互相依賴,或者依賴到同一個共享的狀態(tài)或環(huán)境上,例如當(dāng)前工作目錄、環(huán)境變量等。
如果你不想必行運(yùn)行測試,或者希望精確的控制測試時所啟動的線程數(shù)量,那么可以通過給測試二進(jìn)制文件傳入 —test-threads
標(biāo)記及期望的具體線程數(shù)量來控制這一行為。
cargo test -- --test-threads=1 // 將線程數(shù)量控制為1,這也意味著程序不會使用任何并行操作,使用單線程執(zhí)行測試會比并行話費(fèi)更多的時間,但是順序執(zhí)行不會再因?yàn)楣蚕頎顟B(tài)而出現(xiàn)可能的干擾情形了
4.2. 顯示函數(shù)輸出
默認(rèn)情況下,Rust的測試庫會在測試通過時捕獲所有被打印至標(biāo)準(zhǔn)輸出中的消息。當(dāng)我們測試通過,它所打印的內(nèi)容就無法顯示在終端上;我們只能看到一條用于指明測試通過的消息。只有在測試失敗時,我么你才能在錯誤提示信息的上方觀察到打印至標(biāo)準(zhǔn)輸出中的內(nèi)容。例子:
pub fn add(x: i32, y: i32) -> i32 { println!("x => {}, y => {}", x, y); // @1 x + y } #[cfg(test)] mod tests { use super::*; #[test] fn new_test() { assert_eq!(4, add(2, 2)) } }
我們希望在測試通過時也將值打印出來,那么可以傳入—nocapture標(biāo)記來禁用輸出截獲功能,執(zhí)行下面的命令比較輸出結(jié)果:
cargo test -- --nocapture // 會將@1也輸出顯示 cargo test // 沒有輸出@1
4.3. 只運(yùn)行部分特定名稱的測試
執(zhí)行全部的測試用例有時會花費(fèi)很長時間。而在編寫某個特定部分的代碼時,你也許只需要運(yùn)行和代碼相對應(yīng)地那部分測試。我們可以通過cargo test
中傳遞測試名稱來指定需要運(yùn)行的測試。例子:
pub fn add(x: i32, y: i32) -> i32 { println!("x => {}, y => {}", x, y); x + y } #[cfg(test)] mod tests { use super::*; #[test] fn new_test() { assert_eq!(4, add(2, 2)) } #[test] fn new_test_1() { assert_eq!(5, add(2, 2)) } #[test] fn test_1() { assert_eq!(6, add(2, 2)) } }
這時我們可以指定測試名稱進(jìn)行單獨(dú)測試:
cargo test new_test_1
另外我們可以使用名稱過濾運(yùn)行多個測試:
cargo test new // 此時就會匹配到 new_test 和 new_test_1這兩個測試
4.4. 通過顯示指定來忽略某些測試
有時,一些特定的測試執(zhí)行起來會非常耗時,所有你可能會想要在大部分的cargo test
命令中忽略它們。除了手動將想要運(yùn)行的測試列舉出來,我們也可以使用ignore
屬性來標(biāo)記這些耗時的測試,將這些測試排除在正常的測試運(yùn)行之外。
pub fn add(x: i32, y: i32) -> i32 { println!("x => {}, y => {}", x, y); x + y } #[cfg(test)] mod tests { use super::*; #[test] fn new_test_1() { assert_eq!(5, add(2, 2)) } #[test] #[ignore] fn test_1() { assert_eq!(6, add(2, 2)) } }
此時我們執(zhí)行cargo test
時就可以很明顯的看到ignored
的標(biāo)識:
xxxxxx@xxxxxxx adder % cargo test Finished test [unoptimized + debuginfo] target(s) in 0.00s Running unittests src/lib.rs (target/debug/deps/adder-96bda0c2404f749c) running 3 tests test tests::test_1 ... ignored test tests::new_test ... ok test tests::new_test_1 ... FAILED
此時我們也可以使用cargo test —- —-ignored
來單獨(dú)運(yùn)行這些被忽略的測試。
xxxxx@xxxxxx adder % cargo test -- --ignored Finished test [unoptimized + debuginfo] target(s) in 0.00s Running unittests src/lib.rs (target/debug/deps/adder-96bda0c2404f749c) running 1 test test tests::test_1 ... FAILED failures: ---- tests::test_1 stdout ----
五. 測試的組織結(jié)構(gòu)
Rust社區(qū)主要從以下兩個分類來討論測試:單元測試(unit test
)和集成測試(integration test
)。單元測試小而專注,每次只單獨(dú)測試一個模塊或私有接口。而集成測試完全位于代碼庫之外,和正常從外部調(diào)用代碼一樣使用外部代碼,只能訪問公共接口,而且再一次測試中可能會聯(lián)用多個模塊。
5.1. 單元測試
單元測試的目的在于將一小段代碼單獨(dú)隔離出來,從而迅速確定這段代碼的功能是否符合預(yù)期。我們一般將單元測試與需要測試的代碼存放在src
目錄下的同一文件中。同時也約定俗稱地在每個源代碼文件中都新建一個tests
模塊來存放測試函數(shù),并使用cfg(test)
對該模塊進(jìn)行標(biāo)注。
在tests
模塊上標(biāo)注#[cfg(test)]
可以讓Rust
只在執(zhí)行cargo test
命令時編譯和運(yùn)行該部分測試代碼,而在執(zhí)行cargo build
時剔除它們。這樣就可以在正常編譯時不包含測試代碼,從而節(jié)省編譯時間和產(chǎn)出物所占用的空間。我們不需要對集成測試標(biāo)注#[cfg(test)],因此集成測試本省就放置在獨(dú)立的目錄中。但是,由于本身測試是和業(yè)務(wù)代碼并列放置在同一文件中,所有我們必須使用#[cfg(test)]
進(jìn)行標(biāo)注才能將單元測試的代碼排除在編譯產(chǎn)出物之外。Rust是允許測試私有函數(shù),例子:
// 共有函數(shù) pub fn add(x: i32, y: i32) -> i32 { x + y } // 私有函數(shù) fn sub(x: i32, y: i32) -> i32 { x - y } #[cfg(test)] mod tests { use super::*; #[test] fn add_test() { assert_eq!(4, add(2, 2)) } #[test] fn sub_test() { assert_eq!(0, sub(2, 2)) } }
5.2. 集成測試
在Rust
中,集成測試是完全位于代碼庫之外的。集成個測試調(diào)用庫的方式和其他的代碼調(diào)用方式?jīng)]有任何不同,這也意味著你只能調(diào)用對外公開提供的那部分接口。集成測試的目的在于驗(yàn)證庫的不同部分能否協(xié)同起來工作。能夠獨(dú)立對外公開提供的那部分接口。集成測試的目的在于驗(yàn)證庫的不同部分能否協(xié)同起來正常工作。能夠獨(dú)立正常工作的單元代碼的集成運(yùn)行時也會發(fā)生各種問題,所有集成測試的覆蓋同樣是非常重要的。
為了創(chuàng)建集成測試,我們需要首先建立一個tests
目錄。tests
是文件夾和src
文件夾并列。Cargo
會自動在這個目錄下尋找集成測試文件。在這個目錄下創(chuàng)建任意多個測試文件,Cargo
在編譯時會將每個文件都處理為一個獨(dú)立的包。
我們在執(zhí)行cargo test
xxxxxx@xxxxxxx adder % cargo test Compiling adder v0.1.0 (/rust-example/adder) Finished test [unoptimized + debuginfo] target(s) in 0.15s Running unittests src/lib.rs (target/debug/deps/adder-96bda0c2404f749c) running 1 test test tests::add_test ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Running tests/adder_test.rs (target/debug/deps/adder_test-4bc3058753e422c8). // 執(zhí)行集成測試 running 1 test test it_adds_two ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Doc-tests adder running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
如果此時有多個測試函數(shù),我們可以指定函數(shù)名,單獨(dú)運(yùn)行特定的集成測試函數(shù):
cargo test --test add_test
隨著集成測試增加,我們可以把tests目錄下的代碼分離到多個文件中。將每個集成測試的文件編譯成獨(dú)立的包有助于隔離作用域,并使集成測試環(huán)境更加貼近于用戶的使用場景。
但是在tests目錄中添加模塊并不是簡單的添加一個文件,如圖:
接著我們就可以在測試函數(shù)中引用了
mod common; // 引入模塊 use adder; #[test] fn it_adds_two() { common::setup(); // 調(diào)用 assert_eq!(4, adder::add(2, 2)) }
最后需要注意一點(diǎn),如果我們的項(xiàng)目是一個只有src/main.rs
文件而沒有src/lib.rs
文件的二進(jìn)制包,那么我們就無法在tests目錄中創(chuàng)建集成測試,也無法使用過use
將src/main.rs
中定義的函數(shù)導(dǎo)入作用域。只有代碼包(library crate
)才可以將函數(shù)暴露給其他包調(diào)用,而二進(jìn)制包只被用于獨(dú)立執(zhí)行。
以上就是Rust編寫自動化測試實(shí)例權(quán)威指南的詳細(xì)內(nèi)容,更多關(guān)于Rust編寫自動化測試的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Go調(diào)用Rust方法及外部函數(shù)接口前置
這篇文章主要為大家介紹了Go調(diào)用Rust方法及外部函數(shù)接口前置示例實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06Rust使用csv crate構(gòu)建CSV文件讀取器的全過程
這篇文章主要學(xué)習(xí)如何基于Rust使用csv這個crate構(gòu)建一個CSV文件讀取器的過程,學(xué)習(xí)了csv相關(guān)的用法以及一些往期學(xué)過的crate的復(fù)習(xí),兼顧了實(shí)用性和Rust的學(xué)習(xí),需要的朋友可以參考下2024-05-05