深入了解Rust中泛型的使用
楔子
所有的編程語(yǔ)言都致力于將重復(fù)的任務(wù)簡(jiǎn)單化,并為此提供各種各樣的工具。在 Rust 中,泛型(generics)就是這樣一種工具,它是具體類型或其它屬性的抽象替代。在編寫代碼時(shí),我們可以直接描述泛型的行為,以及與其它泛型產(chǎn)生的聯(lián)系,而無(wú)須知曉它在編譯和運(yùn)行代碼時(shí)采用的具體類型。
總結(jié)一下泛型就是,提高代碼的復(fù)用能力,處理重復(fù)代碼。泛型是具體類型或者其它屬性的抽象代替,編寫的泛型代碼不是最終的代碼,而是一些模板,里面有一些占位符,編譯器在編譯的時(shí)候會(huì)將占位符替換為具體的類型。
函數(shù)中的泛型
函數(shù)中定義泛型的時(shí)候,我們需要將泛型定義在函數(shù)的簽名中:
//?這種定義方式是錯(cuò)誤的,因?yàn)?T?不在作用域中 //?我們要將其放在簽名里面 fn?func(arg:?T)?->?T?{ ????arg? } //?這樣做是正確的 fn?func<T>(arg:?T)?->?T?{ ????arg }
里面的 T 就是一個(gè)泛型,它可以代表任意的類型,然后在編譯的時(shí)候會(huì)將其替換成具體的類型,這個(gè)過(guò)程叫做單態(tài)化。
另外這個(gè) T 就是一個(gè)占位符,你換成別的也可以,只是我們一般寫作 T。
這里我們連續(xù)聲明了多個(gè)變量 x,這在 Rust 里面是沒(méi)有問(wèn)題的,因?yàn)?Rust 有一個(gè)變量隱藏機(jī)制。然后再來(lái)看一下變量 x 的類型,雖然泛型 T 可以代表任意類型,但 Rust 在編譯的時(shí)候會(huì)執(zhí)行單態(tài)化,確定泛型的具體類型。
比如傳一個(gè) 123,那么 T 就會(huì)被標(biāo)記為 i32,因此返回的也是 i32,至于其它類型同理。還是那句話,T 只是一個(gè)占位符,至于它到底代表什么類型,取決于我們調(diào)用時(shí)傳遞的值是什么類型。
比如傳遞一個(gè) &str,那么函數(shù)就會(huì)被 Rust 替換成如下:
fn?func(arg:?&str)?->?&str?{ ????arg }
以上過(guò)程被稱為單態(tài)化,Rust 在編譯期間會(huì)將泛型 T 替換成具體的類型。因此如果想使用泛型,那么函數(shù)簽名中的泛型一定要出現(xiàn)在函數(shù)參數(shù)中,然后根據(jù)調(diào)用方傳遞的值的類型,來(lái)確定泛型。
總結(jié)一下:泛型一定要在函數(shù)的簽名中,也就是在函數(shù)后面通過(guò) <> 進(jìn)行指定,否則的話泛型是無(wú)法使用的。此外,泛型還要出現(xiàn)在參數(shù)中,這是毫無(wú)疑問(wèn)的,不然定義泛型干啥。
當(dāng)然啦,泛型不止可以定義一個(gè),定義任意個(gè)都是可以的。
//?如果有多個(gè)泛型,那么在?<>?里面通過(guò)逗號(hào)分隔 //?然后要保證函數(shù)簽名?<>?里面聲明的泛型, //?都要在函數(shù)參數(shù)中出現(xiàn),也就是要將定義的泛型全用上 fn?func<A,?B,?C>( ????arg1:?A,?arg2:?B,?arg3:?C )?->?(C,?A)?{ ????(arg3,?arg1) } fn?main()?{ ????//?函數(shù)?func?定義了三個(gè)泛型,然后返回的類型是?(C,?A) ????//?這里傳遞三個(gè)參數(shù),顯然當(dāng)調(diào)用時(shí),Rust?會(huì)確定泛型代表的類型 ????//?A?是?i32,B?是?f64,C?是?&str ????let?x?=?func(123,?3.14,?"你好"); ????//?泛型可以接收任何類型,那么當(dāng)調(diào)用時(shí) ????//?A?是?Vec<i32>,B?是?[i32;2],C?是?(i32,?i32) ????let?y?=?func(vec![1,?2],?[1,?2],?(3,?4)); }
這里我們定義了三個(gè)泛型,然后返回的類型是 (C, A)。而 Rust 會(huì)根據(jù)參數(shù)的類型,來(lái)確定泛型,所以變量 x 是 (&str, i32) 類型,變量 y 是 ((i32, i32), Vec<i32>) 類型。
事實(shí)上 IDE 也已經(jīng)推斷出來(lái)了,總的來(lái)說(shuō)泛型應(yīng)該不難理解。
結(jié)構(gòu)體中的泛型
如果一個(gè)結(jié)構(gòu)體成員的類型不確定,那么也可以定義為泛型。
struct?Point<T>?{ ????x:?T, ????y:?T }
和函數(shù)一樣,泛型一定要寫在 <> 當(dāng)中作為簽名出現(xiàn),然后才可以使用,相當(dāng)于告訴 Rust 都定義了哪些泛型。然后簽名中的泛型,一定要全部使用,會(huì)根據(jù)函數(shù)調(diào)用時(shí)給參數(shù)傳的值、或者實(shí)例化結(jié)構(gòu)體時(shí)給成員傳的值,來(lái)確定泛型代表哪一種類型。
如果簽名中的泛型沒(méi)有全部使用,那么 Rust 就無(wú)法執(zhí)行單態(tài)化,于是報(bào)錯(cuò)。所以泛型一定要全部使用,再說(shuō)了,不使用的話,定義它干嘛。
struct?Point<T>?{ ????x:?T, ????y:?T } fn?main()?{ ????let?p1?=?Point{x:?11,?y:?22}; ????let?p2?=?Point{x:?11.1,?y:?22.2}; }
T 只是一個(gè)占位符,具體什么類型要由我們傳遞的內(nèi)容決定,可以是 i32,可以是 f64。但由于成員 x 和 y 的類型都是 T,所以它們的類型一定是一樣的,要是 i32 則都是 i32,要是 f64 則都是 f64。
如果希望類型不同,那么只需要兩個(gè)泛型即可。
struct?Point<T,?U>?{ ????x:?T, ????y:?U } fn?main()?{ ????//?x?和?y?的類型可以相同,也可以不同 ????//?因?yàn)樗鼈兌伎梢越邮杖我忸愋? ????let?p1?=?Point{x:?11,?y:?22}; ????let?p2?=?Point{x:?11.1,?y:?22.2}; ????let?p3?=?Point{x:?"11.1",?y:?String::from("satori")}; ????let?p3?=?Point{x:?vec![1,?2,?3],?y:?(1,?2,?3)}; }
還是那句話,泛型可以接收任意類型,想傳啥都行,具體根據(jù)我們傳遞的值來(lái)確定。
枚舉中的泛型
枚舉也是支持泛型的,比如之前使用的 Option<T> 就是一種泛型,它的結(jié)構(gòu)如下:
enum?Option<T>?{ ????Some(T), ????None }
里面的 T 可以代表任意類型,然后我們?cè)賮?lái)自定義一個(gè)枚舉。
//?簽名中的泛型參數(shù)必須都要使用 //?比如函數(shù)簽名的泛型,要全部體現(xiàn)在參數(shù)中 //?枚舉和結(jié)構(gòu)體簽名的泛型,要全部體現(xiàn)在成員中 enum?MyOption<A,?B,?C>?{ ????//?這里?A、B、C?都是我們隨便定義的,可以代指任意類型 ????//?具體是哪種類型,則看我們傳遞了什么 ????Some1(A), ????Some2(B), ????Some3(C), } fn?main()?{ ????//?泛型不影響效率,是因?yàn)?Rust?要進(jìn)行單態(tài)化 ????//?所以泛型究竟代表哪一種類型要提前確定好 ????//?這里必須要顯式指定?x?的類型。枚舉和結(jié)構(gòu)體不同 ????//?結(jié)構(gòu)體每個(gè)成員都要賦值,所以?Rust?能夠基于賦的值推斷出所有的泛型 ????//?但枚舉的話,每次只會(huì)用到里面的一個(gè)成員 ????//?如果還有其它泛型,那么?Rust?就無(wú)法推斷了 ????//?比如這里只能推斷出泛型?C?代表的類型,而?A?和?B?就無(wú)法推斷了 ????//?因此每個(gè)泛型代表什么類型,需要我們手動(dòng)指定好 ????let?x:?MyOption<i32,?f64,?u8>?=?MyOption::Some3(123); ????match?x?{ ????????MyOption::Some1(v)?=>?println!("我是?i32"), ????????MyOption::Some2(v)?=>?println!("我是?f64"), ????????MyOption::Some3(v)?=>?println!("我是?u8"), ????} ????//?泛型可以代表任意類型,指定啥都是可以的 ????let?y:?MyOption<u8,?i32,?String>?= ????????MyOption::Some3(String::from("xxx")); ????match?y?{ ????????MyOption::Some1(v)?=>?println!("我是?u8"), ????????MyOption::Some2(v)?=>?println!("我是?i32"), ????????MyOption::Some3(v)?=>?println!("我是?String"), ????} ???? ????/* ????我是?u8 ????我是?String ????*/ }
如果覺(jué)得上面的例子不好理解的話,那么再舉個(gè)簡(jiǎn)單的例子:
enum?MyOption<T>?{ ????MySome1(T), ????MySome2(i32), ????MySome3(T), ????MyNone } fn?main()?{ ????//?這里我們沒(méi)有指定?x?的類型 ????//?這是因?yàn)?MyOption?只有一個(gè)泛型 ????//?通過(guò)給?MySome1?傳遞的值,可以推斷出?T?的類型 ????let?x?=?MyOption::MySome1(123); ????//?同樣的道理,Rust?可以自動(dòng)推斷,得出?T?是?&str ????let?x?=?MyOption::MySome3("123"); ????//?但此處就無(wú)法自動(dòng)推斷了,因?yàn)橘x值的是?MySome2?成員 ????//?此時(shí)?Rust?獲取不到任何有關(guān)?T?的信息,無(wú)法執(zhí)行推斷 ????//?因此我們需要手動(dòng)指定類型,但仔細(xì)觀察一下聲明 ????//?首先,如果沒(méi)有泛型的話,那么直接?let?x:?MyOption?=?...?即可 ????//?但里面有泛型,所以此時(shí)除了類型之外,還要連同泛型一起指定 ????//?也就是?MyOption<f64> ????let?x:?MyOption<f64>?=?MyOption::MySome2(123); ????//?當(dāng)然泛型可以代表任意類型,此時(shí)的?T?則是一個(gè)?Vec<i32>?類型 ????let?x:?MyOption<Vec<i32>>?=?MyOption::MySome2(123); }
所以一定要注意:在聲明變量的時(shí)候,如果 Rust 不能根據(jù)我們賦的值推斷出泛型代表的類型,那么我們必須要手動(dòng)聲明類型,來(lái)告訴 Rust 泛型的相關(guān)信息,這樣才可以執(zhí)行單態(tài)化。
對(duì)于結(jié)構(gòu)體也是同樣的道理:
struct?Girl1?{ ????field:?i32, } struct?Girl2<T>?{ ????field:?T, } fn?main()?{ ????//?下面兩個(gè)語(yǔ)句類似,只是第二次聲明?g1?的時(shí)候多指定了類型 ????let?g1?=?Girl1?{?field:?123?}; ????let?g1:?Girl1?=?Girl1?{?field:?123?}; ????//?下面兩條語(yǔ)句也是類似的,第二次聲明?g2?的時(shí)候多指定了類型 ????//?但此時(shí)的類型有些不一樣,Girl2?的結(jié)尾多了一個(gè)?<i32> ????//?原因很簡(jiǎn)單,因?yàn)?Girl2?里面有泛型 ????//?所以在顯式指定類型的時(shí)候,還要將泛型代表的類型一塊指定,否則報(bào)錯(cuò) ????let?g2?=?Girl2?{?field:?123?}; ????let?g2:?Girl2<i32>?=?Girl2?{?field:?123?}; }
然后還有一點(diǎn)比較重要,就是在聲明的時(shí)候,只需在 <> 里面指定泛型即可,什么意思呢?舉個(gè)例子:
struct?Girl<E,?T,?W>?{ ????field1:?String, ????field2:?T, ????field3:?W, ????field4:?E, ????field5:?i32, } fn?main()?{ ????//?這里可以不指定類型,因?yàn)?Rust?可以推斷出來(lái) ????//?不過(guò)這里我們就顯式指定。而雖然 Girl 有 5 個(gè)成員 ????//?但泛型的數(shù)量是三個(gè),因此聲明變量的時(shí)候也要指定三個(gè) ????//?由于定義結(jié)構(gòu)體的時(shí)候,泛型順序是?E?T?W ????//?所以這里的?f64?就是?E,u8?就是?T,Vec<i32>?就是?W ????let?g:?Girl<f64,?u8,?Vec<i32>>?=?Girl?{ ????????field1:?String::from("hello"), ????????field2:?123u8, ????????field3:?vec![1,?2,?3], ????????field4:?3.14, ????????field5:?666, ????}; }
以上就是在枚舉中使用泛型,并且針對(duì)泛型的用法稍微多啰嗦了一些。
方法中的泛型
我們也可以對(duì)方法實(shí)現(xiàn)泛型,舉個(gè)例子:
struct?Point<T,?U>?{ ????x:?T, ????y:?U } //?針對(duì)?i32、f64?實(shí)現(xiàn)的方法 //?只有傳遞的?T、U?對(duì)應(yīng)?i32、f64?才可以調(diào)用 impl?Point<i32,?f64>?{ ????fn?m1(&self)?{ ????????println!("我是?m1?方法") ????} } fn?main()?{ ????let?p1?=?Point{x:?123,?y:?3.14}; ????p1.m1();??//?我是?m1?方法 ????let?p2?=?Point{x:?3.14,?y:?123}; ????//p2.m1(); ????//調(diào)用失敗,因?yàn)?T?和?U?不是?i32、f64,而是?f64、i32 ????//所以?p2?無(wú)法調(diào)用?m1?方法 }
可能有人好奇了,聲明方法的時(shí)候不考慮泛型可不可以,也就是 impl Point {}。答案是不可以,如果結(jié)構(gòu)體中有泛型,那么聲明方法的時(shí)候必須指定。但這就產(chǎn)生了一個(gè)問(wèn)題,那就是只有指定類型的結(jié)構(gòu)體才能調(diào)用方法。
比如上述代碼,只有當(dāng) x 和 y 分別為 i32、f64 時(shí),才可以調(diào)用方法,如果我希望所有的結(jié)構(gòu)體實(shí)例都可以調(diào)用呢?
struct?Point<T,?U>?{ ????x:?T, ????y:?U } //?針對(duì)?K、f64?實(shí)現(xiàn)的方法,由于?K?是一個(gè)泛型 //?所以它可以代表任何類型(泛型只是一個(gè)符號(hào)) //?因此不管?T?最終是什么類型,i32?也好、&str?也罷 //?K?都可以接收,只要?U?是?f64?即可 //?然后注意:如果聲明方法時(shí)結(jié)構(gòu)體后面指定了泛型 //?那么必須將使用的泛型在?impl?后面聲明 impl?<K>?Point<K,?f64>?{ ????fn?m1(&self)?{ ????????println!("我是?m1?方法") ????} } //?此時(shí)?K?和?S?都是泛型,那么此時(shí)對(duì)結(jié)構(gòu)體就沒(méi)有要求了 //?因?yàn)椴还?T?和?W?代表什么,K?和?S?都能表示,因?yàn)樗鼈兌际欠盒? impl?<K,?S>?Point<K,?S>?{ ????fn?m2(&self)?{ ????????println!("我是?m2?方法") ????} } //?這里我們沒(méi)有使用泛型,所以也就無(wú)需在?impl?后面聲明 //?但很明顯,此時(shí)結(jié)構(gòu)體實(shí)例如果想調(diào)用?m3?方法 //?那么必須滿足?T?是?u8,W?是?f64 impl?Point<u8,?f64>?{ ????fn?m3(&self)?{ ????????println!("我是?m3?方法") ????} } fn?main()?{ ????//?顯然?p1?可以同時(shí)調(diào)用?m1?和?m2?方法,但?m3?不行 ????//?因?yàn)?m3?要求?T?是一個(gè)?u8,而當(dāng)前是?&str ????let?p1?=?Point{x:?"hello",?y:?3.14}; ????p1.m1();??//?我是?m1?方法 ????p1.m2();??//?我是?m2?方法 ????//?顯然?p2?可以同時(shí)調(diào)用?m1、m2、m3 ????//?另外這里的?x?可以直接寫成?123,無(wú)需在結(jié)尾加上?u8 ????//?因?yàn)?Rust?看到我們調(diào)用了?m3?方法,會(huì)自動(dòng)推斷為?u8 ????let?p2?=?Point{x:?123u8,?y:?3.14}; ????p2.m1();??//?我是?m1?方法 ????p2.m2();??//?我是?m2?方法 ????p2.m3();??//?我是?m3?方法 ????//?顯然?p3?只能調(diào)用?m2?方法,因?yàn)?m2?對(duì)?T?和?W?沒(méi)有要求 ????//?但是像?m3?就不能調(diào)用,因?yàn)樗菫?<u8,?f64>?實(shí)現(xiàn)的方法 ????//?只有當(dāng)?T、W?為?u8、f64?時(shí)才可以調(diào)用 ????//?顯然此時(shí)是不滿足的,因?yàn)槎际?&str,至于?m1?方法也是同理 ????//?所以?p3?只能調(diào)用?m2,這個(gè)方法是為?<K,?S>?實(shí)現(xiàn)的 ????//?而?K?和?S?也是泛型,可以代表任意類型,因此沒(méi)問(wèn)題 ????let?p3?=?Point{x:?"3.14",?y:?"123"}; ????p3.m2();??//?我是?m2?方法 }
然后注意:我們上面的泛型本質(zhì)上針對(duì)的還是結(jié)構(gòu)體,而我們定義方法的時(shí)候也可以指定泛型,其語(yǔ)法和在函數(shù)中定義泛型是一樣的。
#[derive(Debug)] struct?Point<T,?U>?{ ????x:?T, ????y:?U, } //?使用?impl?時(shí)?Point?后面的泛型名稱可以任意 //?比如我們之前起名為?K?和?S,但這樣容易亂,因?yàn)樽帜柑嗔? //?所以建議:使用 impl 時(shí)的泛型和定義結(jié)構(gòu)體時(shí)的泛型保持一致即可 impl<T,?U>?Point<T,?U>?{ ????//?方法類似于函數(shù),它是一個(gè)獨(dú)立的個(gè)體,可以有自己獨(dú)立的泛型 ????//?然后返回值,因?yàn)?Point?里面是泛型,可以代表任意類型 ????//?那么自然也可以是其它的泛型 ????fn?m1<V,?W>(self,?a:?V,?b:?W)?->?Point<U,?W>?{ ????????//?所以返回值的成員?x?的類型是?U,那么它應(yīng)該來(lái)自于?self.y ????????//?成員?y?的類型是?W,它來(lái)自于參數(shù)?b ????????Point?{?x:?self.y,?y:?b?} ????} } fn?main()?{ ????//?T?是?i32,U?是?f64 ????let?p1?=?Point?{?x:?123,?y:?3.14?}; ????//?V?是?&str,W?是?(i32,?i32,?i32) ????println!("{:?}",?p1.m1("xx",?(1,?2,?3))) ????//?Point?{?x:?3.14,?y:?(1,?2,?3)?} }
以上就是 Rust 的泛型,當(dāng)然在工作中我們不會(huì)聲明的這么復(fù)雜,這里只是為了更好掌握泛型的語(yǔ)法。
然后注意一下方法里面的 self,不是說(shuō)方法的第一個(gè)參數(shù)應(yīng)該是引用嗎?理論上是這樣的,但此處不行,而且如果寫成 &self 是會(huì)報(bào)錯(cuò)的,會(huì)告訴我們沒(méi)有實(shí)現(xiàn) Copy 這個(gè) trait。
之所以會(huì)有這個(gè)現(xiàn)象,是因?yàn)槲覀冊(cè)诜祷刂诞?dāng)中將 self.y 賦值給了成員 x。那么問(wèn)題來(lái)了,如果方法的第一個(gè)參數(shù)是引用,就意味著結(jié)構(gòu)體在調(diào)用完方法之后還能繼續(xù)用,那么結(jié)構(gòu)體內(nèi)部所有成員的值都必須有效,否則結(jié)構(gòu)體就沒(méi)法用了。這個(gè)動(dòng)態(tài)數(shù)組相似,如果動(dòng)態(tài)數(shù)組是有效的,那么內(nèi)部的所有元素必須都是有效的,否則就可能訪問(wèn)非法的內(nèi)存。
因此在構(gòu)建返回值、將 self.y 賦值給成員 x 的時(shí)候,就必須將 self.y 拷貝一份,并且還要滿足拷貝完之后數(shù)據(jù)是各自獨(dú)立的,互不影響。如果 self.y 的數(shù)據(jù)全部在棧上(可 Copy 的),那么這是沒(méi)問(wèn)題的;如果涉及到堆,那么只能轉(zhuǎn)移 self.y 的所有權(quán),因?yàn)?Rust 默認(rèn)不會(huì)拷貝堆數(shù)據(jù),但如果轉(zhuǎn)移所有權(quán),那么方法調(diào)用完之后結(jié)構(gòu)體就不能用了,這與我們將第一個(gè)參數(shù)聲明為引用的目的相矛盾。
所以 Rust 要求 self.y 必須是可 Copy 的,也就是數(shù)據(jù)必須都在棧上,這樣才能滿足在不拷貝堆數(shù)據(jù)的前提下,讓 self.y 賦值之后依舊保持有效。但問(wèn)題是,self.y 的類型是 U,而 U 代表啥類型 Rust 又不知道,所以 Rust 認(rèn)為 U 不是可 Copy 的,或者說(shuō)沒(méi)有實(shí)現(xiàn) Copy 這個(gè) trait,于是報(bào)錯(cuò)。
因此第一個(gè)參數(shù)必須聲明為 self,此時(shí)泛型是否實(shí)現(xiàn) Copy 就不重要了,沒(méi)實(shí)現(xiàn)的話會(huì)直接轉(zhuǎn)移所有權(quán)。因?yàn)樵摻Y(jié)構(gòu)體實(shí)例在調(diào)用完方法之后會(huì)被銷毀,不再被使用,那么此時(shí)可以轉(zhuǎn)移內(nèi)部成員的所有權(quán)。正所謂人都沒(méi)了,還要這所有權(quán)有啥用,不如在銷毀之前將成員值的所有權(quán)交給別人。
最后說(shuō)一下泛型代碼的性能,使用泛型的代碼和使用具體類型的速度是一樣的,因此這就要求 Rust 在編譯的時(shí)候能夠推斷出泛型的具體類型,所以類型要明確。
到此這篇關(guān)于深入了解Rust中泛型的使用的文章就介紹到這了,更多相關(guān)Rust泛型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Rust中的Box<T>之堆上的數(shù)據(jù)與遞歸類型詳解
本文介紹了Rust中的Box<T>類型,包括其在堆與棧之間的內(nèi)存分配,性能優(yōu)勢(shì),以及如何利用Box<T>來(lái)實(shí)現(xiàn)遞歸類型和處理大小未知類型,通過(guò)Box<T>,Rust程序員可以更靈活地管理內(nèi)存,避免編譯時(shí)大小不確定的問(wèn)題,并提高代碼的效率和靈活性2025-02-02用rust?寫一個(gè)jar包?class沖突檢測(cè)工具
這篇文章主要介紹了用rust?寫一個(gè)jar包?class沖突檢測(cè)工具?的相關(guān)資料,需要的朋友可以參考下2023-05-05關(guān)于Rust命令行參數(shù)解析以minigrep為例
本文介紹了如何使用Rust的std::env::args函數(shù)來(lái)解析命令行參數(shù),并展示了如何將這些參數(shù)存儲(chǔ)在變量中,隨后,提到了處理文件和搜索邏輯的步驟,包括讀取文件內(nèi)容、搜索匹配項(xiàng)和輸出搜索結(jié)果,最后,總結(jié)了Rust標(biāo)準(zhǔn)庫(kù)在命令行參數(shù)處理中的便捷性和社區(qū)資源的支持2025-02-02Rust語(yǔ)言之trait中的個(gè)方法可以重寫嗎
在Rust中,trait定義了一組方法,這些方法可以被一個(gè)或多個(gè)類型實(shí)現(xiàn),當(dāng)你為某個(gè)類型實(shí)現(xiàn)一個(gè)trait時(shí),你可以為該trait中的每個(gè)方法提供自己的具體實(shí)現(xiàn),本文將給大家介紹一下trait中的個(gè)方法是否可以重寫,需要的朋友可以參考下2023-10-10Rust-使用dotenvy加載和使用環(huán)境變量的過(guò)程詳解
系統(tǒng)的開(kāi)發(fā),測(cè)試和部署離不開(kāi)環(huán)境變量,今天分享在Rust的系統(tǒng)開(kāi)發(fā)中,使用dotenvy來(lái)讀取和使用環(huán)境變量,感興趣的朋友跟隨小編一起看看吧2023-11-11rust中間件actix_web在項(xiàng)目中的使用實(shí)戰(zhàn)
這篇文章主要介紹了rust中間件在項(xiàng)目中的使用實(shí)戰(zhàn),包括自定義中間件,日志中間件,Default?headers,用戶會(huì)話,錯(cuò)誤處理的用法實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01