本篇內(nèi)容主要講解“Rust常用的標(biāo)準(zhǔn)庫工具有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Rust常用的標(biāo)準(zhǔn)庫工具有哪些”吧!
成都創(chuàng)新互聯(lián)公司專業(yè)為企業(yè)提供海珠網(wǎng)站建設(shè)、海珠做網(wǎng)站、海珠網(wǎng)站設(shè)計(jì)、海珠網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、海珠企業(yè)網(wǎng)站模板建站服務(wù),十余年海珠做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

我們一般使用use語句把其他模塊的內(nèi)容引入當(dāng)前模塊中,但對于標(biāo)準(zhǔn)庫中一些非常常用的工具,每次都寫use語句就過于冗余,因此標(biāo)準(zhǔn)庫提供了一個(gè)std::prelude模塊,在這個(gè)模塊中導(dǎo)出一些最常見的工具,然后編譯器為用戶編寫的每一個(gè)crate都自動插入一句話:
use std::prelude::*;
如此,一些最常見的工具就可以直接使用,而無需use了。對這個(gè)std::prelude模塊所包含內(nèi)容的權(quán)衡是需要細(xì)致考量的,因?yàn)槿绻膬?nèi)容過多則會引入很多不被使用的工具,這反倒不美了。當(dāng)下的std::prelude模塊中包含的內(nèi)容在std::prelude::v1中。
除了as關(guān)鍵字可以用來進(jìn)行基本類型之間的轉(zhuǎn)換,Rust還提供了很多trait來實(shí)現(xiàn)自定義類型之間的轉(zhuǎn)換。
AsRef的含義是該類型可以通過調(diào)用as_ref方法得到另外一個(gè)類型的共享引用,同理,AsMut得到的是另外一個(gè)類型的可讀寫引用,它們的定義如下:
pub trait AsRef<T: ?Sized> {
fn as_ref(&self) -> &T;
}
pub trait AsMut<T: ?Sized> {
fn as_mut(&mut self) -> &mut T;
}AsRef很適合用于泛型代碼中,例如,下面的泛型函數(shù)接受各種類型,只要可以被轉(zhuǎn)換為&[u8]即可:
fn iter_bytes<T: AsRef<[u8]>>(arg: &T) {
for i in arg.as_ref() {
println!("{}", i);
}
}
fn main() {
let s = String::from("this is a string");
let v = vec![1, 2, 3];
let c = "hello";
iter_bytes(&s);
iter_bytes(&v);
iter_bytes(&c);
}Borrow、BorrowMut這兩個(gè)trait的設(shè)計(jì)和AsRef、AsMut很類似:
pub trait Borrow<Borrowed: ?Sized> {
fn borrow(&self) -> &Borrowed;
}
pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
fn borrow_mut(&mut self) -> &mut Borrowed;
}但區(qū)別在于兩點(diǎn):
標(biāo)準(zhǔn)庫為所有的T、&T和&mut T默認(rèn)實(shí)現(xiàn)了Borrow、BorrowMut,以Borrow為例:
impl<T: ?Sized> Borrow<T> for T {
fn borrow(&self) -> &T {
self
}
}
impl<T: ?Sized> Borrow<T> for &T {
fn borrow(&self) -> &T {
&**self
}
}
impl<T: ?Sized> Borrow<T> for &mut T {
fn borrow(&self) -> &T {
&**self
}
}Borrow要求返回的類型,必須和原來的類型具備同樣的hash值。這是一個(gè)約定,如果違反了這個(gè)約定,那么把這個(gè)類型放到HashMap里時(shí)可能會出現(xiàn)問題。
AsRef和Borrow都是從&T到&U的轉(zhuǎn)換,而From/Into是從T到U的轉(zhuǎn)換:
pub trait From<T>: Sized {
fn from(_: T) -> Self;
}
pub trait Into<T>: Sized {
fn into(self) -> T;
}由于From和Into是互逆的一組轉(zhuǎn)換,因此標(biāo)準(zhǔn)庫提供了這樣一個(gè)實(shí)現(xiàn):
impl<T, U> Into<U> for T
where
U: From<T>,
{
fn into(self) -> U {
U::from(self)
}
}這段代碼的含義是:如果存在U: From<T>,則為類型T實(shí)現(xiàn)Into<U>。也就是說,我們只需為類型實(shí)現(xiàn)From即可,Into會自動實(shí)現(xiàn)。標(biāo)準(zhǔn)庫中還有一組對應(yīng)的TryFrom和TryInto,他們是為了處理類型轉(zhuǎn)換過程中可能發(fā)生轉(zhuǎn)換錯誤的情況,因此返回值是Result類型。
ToOwned提供一種更泛化的Clone的功能,Clone是從&T類型變量創(chuàng)造一個(gè)新的T類型變量,而ToOwned是從一個(gè)&T類型變量創(chuàng)造一個(gè)新的U類型變量,標(biāo)準(zhǔn)庫中也提供了ToOwned調(diào)用clone方法的默認(rèn)實(shí)現(xiàn):
pub trait ToOwned {
type Owned: Borrow<Self>;
fn to_owned(&self) -> Self::Owned;
fn clone_into(&self, target: &mut Self::Owned) {
*target = self.to_owned();
}
}
impl<T> ToOwned for T
where
T: Clone,
{
type Owned = T;
fn to_owned(&self) -> T {
self.clone()
}
fn clone_into(&self, target: &mut T) {
target.clone_from(self);
}
}ToString提供了其他類型轉(zhuǎn)換為String類型的能力:
pub trait ToString {
fn to_string(&self) -> String;
}標(biāo)準(zhǔn)庫中為所有實(shí)現(xiàn)了Displaytrait的類型默認(rèn)實(shí)現(xiàn)了ToString,而Display可以通過derive實(shí)現(xiàn):
impl<T: fmt::Display + ?Sized> ToString for T {
default fn to_string(&self) -> String {
use fmt::Write;
let mut buf = String::new();
buf.write_fmt(format_args!("{}", self))
.expect("a Display implementation returned an error unexpectedly");
buf
}
}FromStr提供了從字符串切片向其他類型轉(zhuǎn)換的能力:
pub trait FromStr: Sized {
type Err;
fn from_str(s: &str) -> Result<Self, Self::Err>;
}這里的IO指的是標(biāo)準(zhǔn)輸入輸出和文件輸入輸出。
我們之前介紹過的println!宏可以方便地隨手輸出一些信息,但如果要對標(biāo)準(zhǔn)輸入輸出作更精細(xì)的控制,則需要調(diào)用std::io::stdin()函數(shù)和std::io::stdout()函數(shù)來獲取Stdin和Stdout結(jié)構(gòu)體的實(shí)例。這兩個(gè)實(shí)例的簡單用法如下:
use std::io::{self, Read};
fn main() -> io::Result<()> {
let mut buffer = String::new();
let mut stdin = io::stdin();
stdin.read_to_string(&mut buffer)?;
Ok(())
}為了線程安全考慮,每次讀取操作都需要上鎖,這降低了效率。解決的方法是手動調(diào)用lock()方法,但這又增添了使用標(biāo)準(zhǔn)輸入輸出的復(fù)雜度。
事實(shí)上,我們受學(xué)生時(shí)代做各種C語言大作業(yè)的影響,導(dǎo)致我們認(rèn)為標(biāo)準(zhǔn)輸入輸出是非常重要的功能,可我們細(xì)想一下,正兒八經(jīng)的命令行程序誰會用標(biāo)準(zhǔn)輸入來和用戶交互呢?一般都是通過兩種方式,一則是調(diào)用程序的時(shí)候指定參數(shù),另一則是通過文件讀取用戶配置。
文件輸入輸出首先要解決路徑問題。Rust中的字符串類型是String和str,它們都是用utf-8進(jìn)行編碼的。但是,在具體的操作系統(tǒng)上并不是統(tǒng)一使用utf-8編碼,為了應(yīng)付這種情況,Rust中設(shè)計(jì)了OsString和OsStr,這兩種類型使用方法和String和str類似,并且它們之間也可以互相轉(zhuǎn)換。
Rust標(biāo)準(zhǔn)庫提供了std::path::PathBuf和std::path::Path來處理路徑,PathBuf對內(nèi)部數(shù)據(jù)擁有所有權(quán),而Path只是借用,事實(shí)上,PathBuf內(nèi)部存儲了一個(gè)OsString,而Path則是存儲了Path。
Rust的文件操作主要通過std::fs::File來完成,可以實(shí)現(xiàn)打開、創(chuàng)建、復(fù)制等文件操作。對于文件的讀寫,就要用到std::io模塊中的一些trait了,例如Read和Write。File實(shí)現(xiàn)了這 兩個(gè)trait,因此擁有read等讀取文件的方法。
下面看一個(gè)例子來演示說明文件輸入輸出的方法:
use std::fs::File;
use std::io::{BufRead, BufReader, Read};
fn test_read_file() -> Result<(), std::io::Error> {
let mut path = std::env::current_dir().unwrap();
path.push("Cargo.toml");
let mut file = File::open(&path)?;
let mut buffer = String::new();
file.read_to_string(&mut buffer)?;
println!("{}", buffer);
Ok(())
}
fn main() {
match test_read_file() {
Ok(_) => {}
Err(e) => {
println!("{}", e);
}
}
}和C++的STL類似,Rust的標(biāo)準(zhǔn)庫也給我們提供了一些比較常用的容器以及相關(guān)的迭代器,目前實(shí)現(xiàn)了的容器有:
| 容器 | 描述 |
|---|---|
| Vec | 可變長數(shù)組,連續(xù)存儲 |
| VecDeque | 雙向隊(duì)列,適用于從頭部和尾部插入刪除數(shù)據(jù) |
| LinkedList | 雙向鏈表,非連續(xù)存儲 |
| HashMap | 基于Hash算法存儲一系列鍵值對 |
| BTreeMap | 基于B樹存儲一系列鍵值對 |
| HashSet | 相當(dāng)于沒有值的HashMap |
| BTreeSet | 相當(dāng)于沒有值的BTreeMap |
| BinaryHeap | 基于二叉堆實(shí)現(xiàn)的優(yōu)先級隊(duì)列 |
這里不詳細(xì)展開講,以后會對各個(gè)容器的用法和實(shí)現(xiàn)原理進(jìn)行深入探究。
Rust中的迭代器是指實(shí)現(xiàn)了std::iter::Iterator這個(gè)trait的類型,其定義如下:
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
...
}它最主要的方法是next(),返回一個(gè)Option<Item>,迭代完成則返回None。實(shí)現(xiàn)了Iterator的類型可直接用于for循環(huán)。
迭代器擁有一個(gè)很重要的特性,就是它是可組合的,這有點(diǎn)類似于Java中的流式編程。Iterator中有很多方法,它們返回的類型也實(shí)現(xiàn)了Iterator,這意味著,我們調(diào)用這些方法可以從一個(gè)迭代器創(chuàng)造出一個(gè)新的迭代器,例如:
fn main() {
let v = vec![1, 2, 3, 4, 5, 6, 7, 8];
let mut iter = v
.iter()
.take(5)
.filter(|&x| x % 2 == 0)
.map(|&x| x * x)
.enumerate();
while let Some((i, v)) = iter.next() {
println!("{}: {}", i, v);
}
}這段代碼的含義是:從v這個(gè)Vec的前五個(gè)元素中篩選元素,要求它必須是2的倍數(shù),并把該元素進(jìn)行平方,因此,最終的輸出結(jié)果是0: 4和1: 16。
Rust支持自定義類型重載部分運(yùn)算符,只需該類型實(shí)現(xiàn)std::ops模塊下相應(yīng)的trait即可。以Add為例:
pub trait Add<Rhs = Self> {
type Output;
fn add(self, rhs: Rhs) -> Self::Output;
}它具備一個(gè)泛型參數(shù)RHS和一個(gè)關(guān)聯(lián)類型Output。標(biāo)準(zhǔn)庫中早已為基本的數(shù)字類型實(shí)現(xiàn)了這個(gè)trait:
macro_rules! add_impl {
($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
impl Add for $t {
type Output = $t;
#[inline]
#[rustc_inherit_overflow_checks]
fn add(self, other: $t) -> $t { self + other }
}
forward_ref_binop! { impl Add, add for $t, $t }
)*)
}
add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }到此,相信大家對“Rust常用的標(biāo)準(zhǔn)庫工具有哪些”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
名稱欄目:Rust常用的標(biāo)準(zhǔn)庫工具有哪些
標(biāo)題URL:http://chinadenli.net/article16/gdgegg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營銷、靜態(tài)網(wǎng)站、建站公司、外貿(mào)網(wǎng)站建設(shè)、標(biāo)簽優(yōu)化、用戶體驗(yàn)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)