国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

半小時(shí)入門 Rust?是的,你沒看錯(cuò)

共 25972字,需瀏覽 52分鐘

 ·

2021-12-09 13:12

對(duì) Rust 稍微了解的朋友,對(duì)其學(xué)習(xí)難度應(yīng)該有所耳聞。但今天這篇文章,作者試圖讓新手半小時(shí)入門 Rust。你信嗎?要不試試?

Rust 是一門系統(tǒng)編程語言,專注于安全:包括內(nèi)存安全、并發(fā)安全等。它支持函數(shù)式和命令式以及泛型等多種編程范式。

在這篇文章中,作者并不關(guān)注于 1 個(gè)或幾個(gè)關(guān)鍵概念,相反他希望通過代碼塊縱覽 Rust 的各種特性,包括各種關(guān)鍵詞與標(biāo)識(shí)符的意義。多讀代碼,通過代碼學(xué)習(xí)。(螃蟹哥建議:別只是讀,動(dòng)手敲代碼更重要)

01 變量

先介紹 let 變量綁定:(注意,Rust 中一般稱之為綁定)

let?x;??//?declare?"x"
x?=?42;?//?assign?42?to?"x"

你也可以寫成一行:

let?x?=?42;

通常,Rust 能夠自動(dòng)推斷出變量的類型,但你可以使用 : 來顯示指定變量的數(shù)據(jù)類型:(有時(shí)候必須顯示指定)

let?x:?i32;?//?`i32`?is?a?signed?32-bit?integer
x?=?42;

//?there's?i8,?i16,?i32,?i64,?i128
//????also?u8,?u16,?u32,?u64,?u128?for?unsigned

同樣的,你也可以寫成一行(一般建議這么寫):

let?x:?i32?=?42;

如果你聲明一個(gè)變量并在初始化之前就調(diào)用它,編譯器會(huì)報(bào)錯(cuò):

let?x;
foobar(x);?//?error:?borrow?of?possibly-uninitialized?variable:?`x`
x?=?42;

然而,這樣做完全沒問題:

let?x;
x?=?42;
foobar(x);?//?the?type?of?`x`?will?be?inferred?from?here

下劃線 _ 是一個(gè)特殊的變量名,或者更確切地說是「名稱的缺失」。它的基本意思是扔掉,可以理解為垃圾桶:(和 Go 中的 _ 差不多)

//?this?does?*nothing*?because?42?is?a?constant
let?_?=?42;

//?this?calls?`get_thing`?but?throws?away?its?result
let?_?=?get_thing();

以下劃線開頭的變量名是常規(guī)名稱,只是編譯器不會(huì)警告它們未被使用:

//?we?may?use?`_x`?eventually,?but?our?code?is?a?work-in-progress
//?and?we?just?wanted?to?get?rid?of?a?compiler?warning?for?now.
let?_x?=?42;

可以引入具有相同名稱的另一個(gè)綁定——這相當(dāng)于隱藏前一個(gè)變量綁定:

let?x?=?13;
let?x?=?x?+?3;
//?using?`x`?after?that?line?only?refers?to?the?second?`x`,
//?the?first?`x`?no?longer?exists.

Rust 有元組類型,你可以將其看作是“不同類型值的定長(zhǎng)集合”。

let?pair?=?('a',?17);
pair.0;?//?this?is?'a'
pair.1;?//?this?is?17

如果真的想顯示指定 pair 的數(shù)據(jù)類型,可以這么寫:

let?pair:?(char,?i32)?=?('a',?17);

元組在賦值時(shí)可以被拆解,也就是它們可以被分解成各自的字段:

let?(some_char,?some_int)?=?('a',?17);
//?now,?`some_char`?is?'a',?and?`some_int`?is?17

一個(gè)函數(shù)可以返還一個(gè)元組,這類似于多返回值:

let?(left,?right)?=?slice.split_at(middle);

當(dāng)然,在解構(gòu)一個(gè)元組時(shí),可以只分離它的一部分,這就用到了 _

let?(_,?right)?=?slice.split_at(middle);

分號(hào)表示語句的結(jié)尾:

let?x?=?3;
let?y?=?5;
let?z?=?y?+?x;

不加分號(hào)意味著語句可以跨多行:(這些是什么意思,稍后解釋)

let?x?=?vec![1,?2,?3,?4,?5,?6,?7,?8]
????.iter()
????.map(|x|?x?+?3)
????.fold(0,?|x,?y|?x?+?y);

02 函數(shù)

fn 用來聲明一個(gè)函數(shù)。下面是一個(gè) void 函數(shù)(沒有參數(shù),沒有返回值):

fn?greet()?{
????println!("Hi?there!");
}

這是一個(gè)返回 32 位帶符號(hào)整數(shù)類型的函數(shù)。箭頭表示它的返回類型:

fn?fair_dice_roll()?->?i32?{
????4
}

花括號(hào)表示一個(gè)代碼塊,且擁有其自己的作用域:

//?This?prints?"in",?then?"out"
fn?main()?{
????let?x?=?"out";
????{
????????//?this?is?a?different?`x`
????????let?x?=?"in";
????????println!("{}",?x);
????}
????println!("{}",?x);
}

代碼塊也是表示式,最后一個(gè)表達(dá)式的值是整個(gè)代碼塊的值,以下代碼表達(dá)的意思一樣:

//?this:
let?x?=?42;

//?is?equivalent?to?this:
let?x?=?{?42?};

在一個(gè)代碼塊中,可以有多個(gè)語句:

let?x?=?{
????let?y?=?1;?//?first?statement
????let?z?=?2;?//?second?statement
????y?+?z?//?this?is?the?*tail*?-?what?the?whole?block?will?evaluate?to
};

這也是為什么“省略函數(shù)末尾的分號(hào)”等同于加上了 retrun,以下是等價(jià)的:

fn?fair_dice_roll()?->?i32?{
????return?4;
}

fn?fair_dice_roll()?->?i32?{
????4
}

if 條件語句也是表達(dá)式:

fn?fair_dice_roll()?->?i32?{
????if?feeling_lucky?{
????????6
????}?else?{
????????4
????}
}

match 也是一個(gè)表達(dá)式:

fn?fair_dice_roll()?->?i32?{
????match?feeling_lucky?{
????????true?=>?6,
????????false?=>?4,
????}
}

Dots(點(diǎn)號(hào)) 通常用于訪問某個(gè)對(duì)象的字段:

let?a?=?(10,?20);
a.0;?//?this?is?10

let?amos?=?get_some_struct();
amos.nickname;?//?this?is?"fasterthanlime"

或者調(diào)用對(duì)象(值)的方法:

let?nick?=?"fasterthanlime";
nick.len();?//?this?is?14

雙冒號(hào)(::)與此類似,但它是對(duì)命名空間進(jìn)行操作。

在這個(gè)例子中,std 是一個(gè) crate (~ a library),cmp 是一個(gè) module(~ a source file),而 min 是個(gè)函數(shù):

let?least?=?std::cmp::min(3,?8);?//?this?is?3

use 指令可用于從其他命名空間中“引入作用域(scope)”名稱:

use?std::cmp::min;

let?least?=?min(7,?1);?//?this?is?1

在 use 指令中,花括號(hào)還有另一個(gè)含義:“globs”。如果我們想同時(shí)導(dǎo)入 min 和 max,可以這么做:

//?this?works:
use?std::cmp::min;
use?std::cmp::max;

//?this?also?works:
use?std::cmp::{min,?max};

//?this?also?works!
use?std::{cmp::min,?cmp::max};

通配符(*)允許從命名空間導(dǎo)入符號(hào):

//?this?brings?`min`?and?`max`?in?scope,?and?many?other?things
use?std::cmp::*;

類型也相當(dāng)于命名空間,通過 :: 調(diào)用其上的方法,以下兩種方式等價(jià):

let?x?=?"amos".len();?//?this?is?4
let?x?=?str::len("amos");?//?this?is?also?4

str 是基本數(shù)據(jù)類型(primitive type),但在默認(rèn)情況下,許多非基本數(shù)據(jù)類型也在當(dāng)前作用域中(即不需要手動(dòng) use 導(dǎo)入)。

//?`Vec`?is?a?regular?struct,?not?a?primitive?type
let?v?=?Vec::new();

//?this?is?exactly?the?same?code,?but?with?the?*full*?path?to?`Vec`
let?v?=?std::vec::Vec::new();

為什么可以這么做呢?為了方便,Rust 在每個(gè)模塊的開頭都插入了以下代碼(我認(rèn)為類似 Java 默認(rèn)導(dǎo)入 java.lang 包):

use?std::prelude::v1::*;

以上代碼會(huì)以此導(dǎo)出許多標(biāo)識(shí)符,比如 Vec、String、Option、Result。

03 結(jié)構(gòu)體

使用 struct 關(guān)鍵字聲明結(jié)構(gòu)體:

struct?Vec2?{
????x:?f64,?//?64-bit?floating?point,?aka?"double?precision"
????y:?f64,
}

可以使用結(jié)構(gòu)語句初始化:

let?v1?=?Vec2?{?x:?1.0,?y:?3.0?};
let?v2?=?Vec2?{?y:?2.0,?x:?4.0?};
//?the?order?does?not?matter,?only?the?names?do

有一個(gè)快捷方式可以從另一個(gè)結(jié)構(gòu)體初始化本結(jié)構(gòu)體的其余字段:

let?v3?=?Vec2?{
????x:?14.0,
????..v2
};

這就是所謂的“結(jié)構(gòu)更新語法”,只能發(fā)生在最后一個(gè)位置,而且不能在其后面再跟一個(gè)逗號(hào)。

注意其余字段可以表示所有字段:

let?v4?=?Vec2?{?..v3?};

結(jié)構(gòu)體與元組一樣,可以被解構(gòu)。就像是一個(gè)有效的 let 模式:

let?(left,?right)?=?slice.split_at(middle);

let?v?=?Vec2?{?x:?3.0,?y:?6.0?};
let?Vec2?{?x,?y?}?=?v;
//?`x`?is?now?3.0,?`y`?is?now?`6.0`

還可以這樣:

let?Vec2?{?x,?..?}?=?v;
//?this?throws?away?`v.y`

let 模式可以作為 if 的條件使用:

struct?Number?{
????odd:?bool,
????value:?i32,
}

fn?main()?{
????let?one?=?Number?{?odd:?true,?value:?1?};
????let?two?=?Number?{?odd:?false,?value:?2?};
????print_number(one);
????print_number(two);
}

fn?print_number(n:?Number)?{
????if?let?Number?{?odd:?true,?value?}?=?n?{
????????println!("Odd?number:?{}",?value);
????}?else?if?let?Number?{?odd:?false,?value?}?=?n?{
????????println!("Even?number:?{}",?value);
????}
}

//?this?prints:
//?Odd?number:?1
//?Even?number:?2

多分支的 match 也是一種模式,就像 if let:

fn?print_number(n:?Number)?{
????match?n?{
????????Number?{?odd:?true,?value?}?=>?println!("Odd?number:?{}",?value),
????????Number?{?odd:?false,?value?}?=>?println!("Even?number:?{}",?value),
????}
}

//?this?prints?the?same?as?before

match 必須是囊括所有情況的的:至少需要匹配一個(gè)分支(Rust 中叫做 arm)。

fn?print_number(n:?Number)?{
????match?n?{
????????Number?{?value:?1,?..?}?=>?println!("One"),
????????Number?{?value:?2,?..?}?=>?println!("Two"),
????????Number?{?value,?..?}?=>?println!("{}",?value),
????????//?if?that?last?arm?didn't?exist,?we?would?get?a?compile-time?error
????}
}

如果實(shí)在沒法包含所有情況,可以增加一個(gè) _ 來捕獲所有其他情況,類似其他語言 switch 的 default:

fn?print_number(n:?Number)?{
????match?n.value?{
????????1?=>?println!("One"),
????????2?=>?println!("Two"),
????????_?=>?println!("{}",?n.value),
????}
}

你可以在自定義類型上聲明方法:

struct?Number?{
????odd:?bool,
????value:?i32,
}

impl?Number?{
????fn?is_strictly_positive(self)?->?bool?{
????????self.value?>?0
????}
}

然后像平常一樣使用:

fn?main()?{
????let?minus_two?=?Number?{
????????odd:?false,
????????value:?-2,
????};
????println!("positive??{}",?minus_two.is_strictly_positive());
????//?this?prints?"positive??false"
}

默認(rèn)情況下,聲明變量后它是不可變的,比如以下 odd 不能被重新賦值:

fn?main()?{
????let?n?=?Number?{
????????odd:?true,
????????value:?17,
????};
????n.odd?=?false;?//?error:?cannot?assign?to?`n.odd`,
???????????????????//?as?`n`?is?not?declared?to?be?mutable
}

整個(gè)結(jié)構(gòu)體值也不能二次賦值:

fn?main()?{
????let?n?=?Number?{
????????odd:?true,
????????value:?17,
????};
????n?=?Number?{
????????odd:?false,
????????value:?22,
????};?//?error:?cannot?assign?twice?to?immutable?variable?`n`
}

關(guān)鍵字 mut 可以將變量聲明變?yōu)榭勺兊模?/p>

fn?main()?{
????let?mut?n?=?Number?{
????????odd:?true,
????????value:?17,
????}
????n.value?=?19;?//?all?good
}

04 trait(特征)

Traits(特征) 描述的是多種數(shù)據(jù)類型的共有的東西:(可以類比為其他語言的接口)

trait?Signed?{
????fn?is_strictly_negative(self)?->?bool;
}

我們可以這么實(shí)現(xiàn):

  • 可以對(duì)外部類型實(shí)現(xiàn)自定義的 trait;
  • 可以對(duì)自定義類型實(shí)現(xiàn)外部 trait;
  • 不允許對(duì)外部類型實(shí)現(xiàn)外部 trait;

這些被稱為“孤兒法則”。你如果有點(diǎn)暈,進(jìn)一步解釋一下:

當(dāng)你為某類型實(shí)現(xiàn)某 trait 的時(shí)候,必須要求類型或者 trait 至少有一個(gè)是在當(dāng)前 crate 中定義的。你不能為第三方的類型實(shí)現(xiàn)第三方的 trait。

此外,這時(shí)記得讓 trait 的方法可訪問(公開)。

可以在我們上面定義的類型(Number)上實(shí)現(xiàn) trait:

impl?Signed?for?Number?{
????fn?is_strictly_negative(self)?->?bool?{
????????self.value?0
????}
}

fn?main()?{
????let?n?=?Number?{?odd:?false,?value:?-44?};
????println!("{}",?n.is_strictly_negative());?//?prints?"true"
}

我們對(duì)外部類型(foreign type)實(shí)現(xiàn)我們定義的 trait:(這里的外部類型使用了基本類型 i32)

impl?Signed?for?i32?{
????fn?is_strictly_negative(self)?->?bool?{
????????self?0
????}
}

fn?main()?{
????let?n:?i32?=?-44;
????println!("{}",?n.is_strictly_negative());?//?prints?"true"
}

接著在我們定義的類型上實(shí)現(xiàn)一個(gè)外部 trait:

//?the?`Neg`?trait?is?used?to?overload?`-`,?the
//?unary?minus?operator.
impl?std::ops::Neg?for?Number?{
????type?Output?=?Number;

????fn?neg(self)?->?Number?{
????????Number?{
????????????value:?-self.value,
????????????odd:?self.odd,
????????}????????
????}
}

fn?main()?{
????let?n?=?Number?{?odd:?true,?value:?987?};
????let?m?=?-n;?//?this?is?only?possible?because?we?implemented?`Neg`
????println!("{}",?m.value);?//?prints?"-987"
}

impl 代碼塊通常會(huì)對(duì)應(yīng)一個(gè)類型,所以在 impl 內(nèi),Self 就表示該類型:

impl?std::ops::Neg?for?Number?{
????type?Output?=?Self;

????fn?neg(self)?->?Self?{
????????Self?{
????????????value:?-self.value,
????????????odd:?self.odd,
????????}
????}
}

有一些 trait 只是作為標(biāo)記:它們并不是說某個(gè)類型實(shí)現(xiàn)了某些方法,只是表明某些東西能通過類型完成。例如,i32 實(shí)現(xiàn)了 Copy trait,那么以下代碼就是可行的:(即 i32 是一個(gè) Copy)

fn?main()?{
????let?a:?i32?=?15;
????let?b?=?a;?//?`a`?is?copied
????let?c?=?a;?//?`a`?is?copied?again
}

下面的代碼也是能運(yùn)行的:

fn?print_i32(x:?i32)?{
????println!("x?=?{}",?x);
}

fn?main()?{
????let?a:?i32?=?15;
????print_i32(a);?//?`a`?is?copied
????print_i32(a);?//?`a`?is?copied?again
}

但是 Number 的結(jié)構(gòu)體并不是一個(gè) Copy,所以下面的代碼會(huì)報(bào)錯(cuò):

fn?main()?{
????let?n?=?Number?{?odd:?true,?value:?51?};
????let?m?=?n;?//?`n`?is?moved?into?`m`
????let?o?=?n;?//?error:?use?of?moved?value:?`n`
}

同樣下面的代碼也不會(huì)正常:

fn?print_number(n:?Number)?{
????println!("{}?number?{}",?if?n.odd?{?"odd"?}?else?{?"even"?},?n.value);
}

fn?main()?{
????let?n?=?Number?{?odd:?true,?value:?51?};
????print_number(n);?//?`n`?is?moved
????print_number(n);?//?error:?use?of?moved?value:?`n`
}

但如果 print _ number 采用不可變引用,那么它就可以正常工作:

fn?print_number(n:?&Number)?{
????println!("{}?number?{}",?if?n.odd?{?"odd"?}?else?{?"even"?},?n.value);
}

fn?main()?{
????let?n?=?Number?{?odd:?true,?value:?51?};
????print_number(&n);?//?`n`?is?borrowed?for?the?time?of?the?call
????print_number(&n);?//?`n`?is?borrowed?again
}

如果一個(gè)函數(shù)接受一個(gè)可變的引用,它也可以工作,但前提是我們的變量綁定也是可變的。

fn?invert(n:?&mut?Number)?{
????n.value?=?-n.value;
}

fn?print_number(n:?&Number)?{
????println!("{}?number?{}",?if?n.odd?{?"odd"?}?else?{?"even"?},?n.value);
}

fn?main()?{
????//?this?time,?`n`?is?mutable
????let?mut?n?=?Number?{?odd:?true,?value:?51?};
????print_number(&n);
????invert(&mut?n);?//?`n?is?borrowed?mutably?-?everything?is?explicit
????print_number(&n);
}

trait 方法也可以通過 self 進(jìn)行引用或可變引用:

impl?std::clone::Clone?for?Number?{
????fn?clone(&self)?->?Self?{
????????Self?{?..*self?}
????}
}

當(dāng)調(diào)用 trait 方法時(shí),接收方隱式地被借用:

fn?main()?{
????let?n?=?Number?{?odd:?true,?value:?51?};
????let?mut?m?=?n.clone();
????m.value?+=?100;
????
????print_number(&n);
????print_number(&m);
}

沒理解什么意思?以下是等價(jià)的,你該理解了:

let?m?=?n.clone();

let?m?=?std::clone::Clone::clone(&n);

像 Copy 這樣的標(biāo)記特征沒有方法:

//?note:?`Copy`?requires?that?`Clone`?is?implemented?too
impl?std::clone::Clone?for?Number?{
????fn?clone(&self)?->?Self?{
????????Self?{?..*self?}
????}
}

impl?std::marker::Copy?for?Number?{}

現(xiàn)在 Clone 仍然正常:

fn?main()?{
????let?n?=?Number?{?odd:?true,?value:?51?};
????let?m?=?n.clone();
????let?o?=?n.clone();
}

但是 Number 值將不再被移動(dòng):

fn?main()?{
????let?n?=?Number?{?odd:?true,?value:?51?};
????let?m?=?n;?//?`m`?is?a?copy?of?`n`
????let?o?=?n;?//?same.?`n`?is?neither?moved?nor?borrowed.
}

有些特性非常常見,它們可以通過 derive 屬性自動(dòng)實(shí)現(xiàn):

#[derive(Clone,?Copy)]
struct?Number?{
????odd:?bool,
????value:?i32,
}

//?this?expands?to?`impl?Clone?for?Number`?and?`impl?Copy?for?Number`?blocks.

05 泛型

函數(shù)支持泛型:

fn?foobar(arg:?T)?{
????//?do?something?with?`arg`
}

它們可以有多個(gè)類型參數(shù),這些參數(shù)可以在函數(shù)的聲明和函數(shù)體中使用,而不是具體類型:

fn?foobar(left:?L,?right:?R)?{
????//?do?something?with?`left`?and?`right`
}

類型參數(shù)通常有約束,因此你可以實(shí)際使用它們。

最簡(jiǎn)單的限制是特征(trait)名:

fn?print(value:?T)?{
????println!("value?=?{}",?value);
}

fn?printDebug>(value:?T)?{
????println!("value?=?{:?}",?value);
}

類型參數(shù)約束有一個(gè)更長(zhǎng)的語法:

fn?print(value:?T)
where
????T:?Display,
{
????println!("value?=?{}",?value);
}

約束可能更復(fù)雜:它們可能需要一個(gè)類型參數(shù)來實(shí)現(xiàn)多個(gè) traits:

use?std::fmt::Debug;

fn?compare(left:?T,?right:?T)
where
????T:?Debug?+?PartialEq,
{
????println!("{:?}?{}?{:?}",?left,?if?left?==?right?{?"=="?}?else?{?"!="?},?right);
}

fn?main()?{
????compare("tea",?"coffee");
????//?prints:?"tea"?!=?"coffee"
}

泛型函數(shù)可以看作是命名空間,包含無數(shù)具有不同具體類型的函數(shù)。

與 crates、modules 和 類型一樣,泛型函數(shù)可以通過 :: 指定具體類型:

fn?main()?{
????use?std::any::type_name;
????println!("{}",?type_name::<i32>());?//?prints?"i32"
????println!("{}",?type_name::<(f64,?char)>());?//?prints?"(f64,?char)"
}

這就是所謂的 turbofish 語法,因?yàn)?::<> 看起來像一條魚。

結(jié)構(gòu)體也可以是泛型:

struct?Pair?{
????a:?T,
????b:?T,
}

fn?print_type_name(_val:?&T)?{
????println!("{}",?std::any::type_name::());
}

fn?main()?{
????let?p1?=?Pair?{?a:?3,?b:?9?};
????let?p2?=?Pair?{?a:?true,?b:?false?};
????print_type_name(&p1);?//?prints?"Pair"
????print_type_name(&p2);?//?prints?"Pair"
}

標(biāo)準(zhǔn)庫類型 Vec(堆分配數(shù)組)是泛型的:

fn?main()?{
????let?mut?v1?=?Vec::new();
????v1.push(1);
????let?mut?v2?=?Vec::new();
????v2.push(false);
????print_type_name(&v1);?//?prints?"Vec"
????print_type_name(&v2);?//?prints?"Vec"
}

06 宏

說到 Vec,它附帶了一個(gè)宏 “Vec 字面值”。

fn?main()?{
????let?v1?=?vec![1,?2,?3];
????let?v2?=?vec![true,?false,?true];
????print_type_name(&v1);?//?prints?"Vec"
????print_type_name(&v2);?//?prints?"Vec"
}

所有的 name!(),name![] 或 name!{} 都是在調(diào)用宏。宏最終會(huì)展開為常規(guī)代碼。

所以,println 也是一個(gè)宏。

fn?main()?{
????println!("{}",?"Hello?there!");
}

這個(gè)會(huì)展開為和下面有相同效果的代碼:

fn?main()?{
????use?std::io::{self,?Write};
????io::stdout().lock().write_all(b"Hello?there!\n").unwrap();
}

panic 也是一個(gè)宏。如果調(diào)用了它,會(huì)使用錯(cuò)誤消息以及錯(cuò)誤的文件名/行號(hào)強(qiáng)制停止執(zhí)行:

fn?main()?{
????panic!("This?panics");
}
//?output:?thread?'main'?panicked?at?'This?panics',?src/main.rs:3:5

有些方法也會(huì)引起 panic。例如,Option 類型可以包含某些內(nèi)容,也可以不包含任何內(nèi)容。如果調(diào)用 Unwrap(),但它不包含任何內(nèi)容,就會(huì) panic:

fn?main()?{
????let?o1:?Option<i32>?=?Some(128);
????o1.unwrap();?//?this?is?fine

????let?o2:?Option<i32>?=?None;
????o2.unwrap();?//?this?panics!
}

//?output:?thread?'main'?panicked?at?'called?`Option::unwrap()`?on?a?`None`?value',?src/libcore/option.rs:378:21

07 枚舉

Option 不是結(jié)構(gòu)體,而是帶有兩個(gè)變體的枚舉:

enum?Option?{
????None,
????Some(T),
}

impl?Option?{
????fn?unwrap(self)?->?T?{
????????//?enums?variants?can?be?used?in?patterns:
????????match?self?{
????????????Self::Some(t)?=>?t,
????????????Self::None?=>?panic!(".unwrap()?called?on?a?None?option"),
????????}
????}
}

use?self::Option::{None,?Some};

fn?main()?{
????let?o1:?Option<i32>?=?Some(128);
????o1.unwrap();?//?this?is?fine

????let?o2:?Option<i32>?=?None;
????o2.unwrap();?//?this?panics!
}

//?output:?thread?'main'?panicked?at?'.unwrap()?called?on?a?None?option',?src/main.rs:11:27

Result 也是一個(gè)枚舉,它可以包含一些東西,或包含一個(gè)錯(cuò)誤:

enum?Result?{
????Ok(T),
????Err(E),
}

如果 Result 包含錯(cuò)誤時(shí),進(jìn)行 unwrap 操作會(huì) panic。

08 生命周期

變量綁定有一個(gè)“生命周期(lifetime)”:

fn?main()?{
????//?`x`?doesn't?exist?yet
????{
????????let?x?=?42;?//?`x`?starts?existing
????????println!("x?=?{}",?x);
????????//?`x`?stops?existing
????}
????//?`x`?no?longer?exists
}

類似地,引用也有生命周期:

fn?main()?{
????//?`x`?doesn't?exist?yet
????{
????????let?x?=?42;?//?`x`?starts?existing
????????let?x_ref?=?&x;?//?`x_ref`?starts?existing?-?it?borrows?`x`
????????println!("x_ref?=?{}",?x_ref);
????????//?`x_ref`?stops?existing
????????//?`x`?stops?existing
????}
????//?`x`?no?longer?exists
}

引用的生命周期你不能超過其借用的變量綁定的生命周期:

fn?main()?{
????let?x_ref?=?{
????????let?x?=?42;
????????&x
????};
????println!("x_ref?=?{}",?x_ref);
????//?error:?`x`?does?not?live?long?enough
}

一個(gè)變量綁定可以被多次借用:

fn?main()?{
????let?x?=?42;
????let?x_ref1?=?&x;
????let?x_ref2?=?&x;
????let?x_ref3?=?&x;
????println!("{}?{}?{}",?x_ref1,?x_ref2,?x_ref3);
}

在被借用期間,變量綁定不能被修改:

fn?main()?{
????let?mut?x?=?42;
????let?x_ref?=?&x;
????x?=?13;
????println!("x_ref?=?{}",?x_ref);
????//?error:?cannot?assign?to?`x`?because?it?is?borrowed
}

當(dāng)存在不可變借用時(shí),變量不能再次作為可變借用。

fn?main()?{
????let?mut?x?=?42;
????let?x_ref1?=?&x;
????let?x_ref2?=?&mut?x;
????//?error:?cannot?borrow?`x`?as?mutable?because?it?is?also?borrowed?as?immutable
????println!("x_ref1?=?{}",?x_ref1);
}

函數(shù)參數(shù)中的引用也有生命周期:

fn?print(x:?&i32)?{
????//?`x`?is?borrowed?(from?the?outside)?for?the
????//?entire?time?this?function?is?called.
}

帶有引用參數(shù)的函數(shù)可以使用具有不同生命期的 borrows 來調(diào)用,所以:

  • 所有參數(shù)是引用的函數(shù),它們實(shí)際上都是泛型函數(shù);
  • 生命周期就是泛型參數(shù);

生命周期名以單引號(hào) ' 開頭:

//?elided?(non-named)?lifetimes:
fn?print(x:?&i32)?{}

//?named?lifetimes:
fn?print<'a>(x:?&'a?i32)?{}

這允許返回的引用的生命周期依賴于參數(shù)的生命周期:

struct?Number?{
????value:?i32,
}

fn?number_value<'a>(num:?&'a?Number)?->?&'a?i32?{
????&num.value
}

fn?main()?{
????let?n?=?Number?{?value:?47?};
????let?v?=?number_value(&n);
????//?`v`?borrows?`n`?(immutably),?thus:?`v`?cannot?outlive?`n`.
????//?While?`v`?exists,?`n`?cannot?be?mutably?borrowed,?mutated,?moved,?etc.
}

當(dāng)只有一個(gè)輸入生命周期時(shí),它不需要命名,所有的東西都具有相同的生命周期,因此下面的兩個(gè)函數(shù)是等價(jià)的:

fn?number_value<'a>(num:?&'a?Number)?->?&'a?i32?{
????&num.value
}

fn?number_value(num:?&Number)?->?&i32?{
????&num.value
}

當(dāng)有引用字段時(shí),結(jié)構(gòu)體也是基于生命周期的泛型:

struct?NumRef<'a>?{
????x:?&'a?i32,
}

fn?main()?{
????let?x:?i32?=?99;
????let?x_ref?=?NumRef?{?x:?&x?};
????//?`x_ref`?cannot?outlive?`x`,?etc.
}

同樣的代碼,但是有一個(gè)額外的函數(shù):

struct?NumRef<'a>?{
????x:?&'a?i32,
}

fn?as_num_ref<'a>(x:?&'a?i32)?->?NumRef<'a>?{
????NumRef?{?x:?&x?}
}

fn?main()?{
????let?x:?i32?=?99;
????let?x_ref?=?as_num_ref(&x);
????//?`x_ref`?cannot?outlive?`x`,?etc.
}

相同的代碼,但省略了生命期:

struct?NumRef<'a>?{
????x:?&'a?i32,
}

fn?as_num_ref(x:?&i32)?->?NumRef<'_>?{
????NumRef?{?x:?&x?}
}

fn?main()?{
????let?x:?i32?=?99;
????let?x_ref?=?as_num_ref(&x);
????//?`x_ref`?cannot?outlive?`x`,?etc.
}

Impl 塊也可以是基于生命周期的泛型:

impl<'a>?NumRef<'a>?{
????fn?as_i32_ref(&'a?self)?->?&'a?i32?{
????????self.x
????}
}

fn?main()?{
????let?x:?i32?=?99;
????let?x_num_ref?=?NumRef?{?x:?&x?};
????let?x_i32_ref?=?x_num_ref.as_i32_ref();
????//?neither?ref?can?outlive?`x`
}

但你也可以在這里省略:

impl<'a>?NumRef<'a>?{
????fn?as_i32_ref(&self)?->?&i32?{
????????self.x
????}
}

如果你從來不需要這個(gè)名字,你可以省去更多:

impl?NumRef<'_>?{
????fn?as_i32_ref(&self)?->?&i32?{
????????self.x
????}
}

有一個(gè)特殊的生命周期,名為 'static,它對(duì)整個(gè)程序的生命周期都有效。

字符串字面量就是 'static

struct?Person?{
????name:?&'static?str,
}

fn?main()?{
????let?p?=?Person?{
????????name:?"fasterthanlime",
????};
}

但非字面量字符串并不是 static 的:

struct?Person?{
????name:?&'static?str,
}

fn?main()?{
????let?name?=?format!("fasterthan{}",?"lime");
????let?p?=?Person?{?name:?&name?};
????//?error:?`name`?does?not?live?long?enough
}

在最后一個(gè)示例中,局部變量 name 并不是 ?&'static str,而是 String。它是動(dòng)態(tài)分配的,并且會(huì)在不需要釋放。它的生命周期小于整個(gè)程序(即使它碰巧在 main 中)。

要在 Person 中存儲(chǔ)非 'static 字符串,它需要:

A)基于生命周期的泛型:

struct?Person<'a>?{
????name:?&'a?str,
}

fn?main()?{
????let?name?=?format!("fasterthan{}",?"lime");
????let?p?=?Person?{?name:?&name?};
????//?`p`?cannot?outlive?`name`
}

B)取得字符串所有權(quán)

struct?Person?{
????name:?String,
}

fn?main()?{
????let?name?=?format!("fasterthan{}",?"lime");
????let?p?=?Person?{?name:?name?};
????//?`name`?was?moved?into?`p`,?their?lifetimes?are?no?longer?tied.
}

在 struct literal 中,當(dāng)一個(gè)字段被設(shè)置為同名的變量綁定時(shí):

let?p?=?Person?{?name:?name?};

它可以這樣簡(jiǎn)寫:

let?p?=?Person?{?name?};

09 所有權(quán)

對(duì)于 Rust 中的許多類型,存在有所有權(quán)和沒有所有權(quán)之分:

  • Strings:String 是有所有權(quán)的;$str 是一個(gè)引用;
  • Paths:PathBuf 是有所有權(quán)的;$Path 是一個(gè)引用;
  • Collections:Vec 是有所有權(quán)的;&[T] 是一個(gè)引用;

Rust 有切片類型(slice)—— 它們是對(duì)多個(gè)連續(xù)元素的引用。

你可以借用 Vector 的一個(gè)切片,例如:

fn?main()?{
????let?v?=?vec![1,?2,?3,?4,?5];
????let?v2?=?&v[2..4];
????println!("v2?=?{:?}",?v2);
}

//?output:
//?v2?=?[3,?4]

以上并不神奇。索引操作符(foo[index])被 Index 和 IndexMut 特征重載。

.. 語法是 range 字面值,range 是標(biāo)準(zhǔn)庫中定義的幾個(gè)結(jié)構(gòu)體。

它們可以是半閉半開的,如果前面有 = ,那么它們就是閉區(qū)間。

fn?main()?{
????//?0?or?greater
????println!("{:?}",?(0..).contains(&100));?//?true
????//?strictly?less?than?20
????println!("{:?}",?(..20).contains(&20));?//?false
????//?20?or?less?than?20
????println!("{:?}",?(..=20).contains(&20));?//?true
????//?only?3,?4,?5
????println!("{:?}",?(3..6).contains(&4));?//?true
}

借用規(guī)則適用于切片。

fn?tail(s:?&[u8])?->?&[u8]?{
??&s[1..]?
}

fn?main()?{
????let?x?=?&[1,?2,?3,?4,?5];
????let?y?=?tail(x);
????println!("y?=?{:?}",?y);
}

這和下面的一樣:

fn?tail<'a>(s:?&'a?[u8])?->?&'a?[u8]?{
??&s[1..]?
}

以下是合法的:

fn?main()?{
????let?y?=?{
????????let?x?=?&[1,?2,?3,?4,?5];
????????tail(x)
????};
????println!("y?=?{:?}",?y);
}

但因?yàn)?[1,2,3,4,5] 是一個(gè) 'static 數(shù)組。所以,以下是非法的:

fn?main()?{
????let?y?=?{
????????let?v?=?vec![1,?2,?3,?4,?5];
????????tail(&v)
????????//?error:?`v`?does?not?live?long?enough
????};
????println!("y?=?{:?}",?y);
}

因?yàn)?Vector 是在堆分配的,而且它的生命周期是非 'static 的。

&str 實(shí)際上是切片。

fn?file_ext(name:?&str)?->?Option<&str>?{
????//?this?does?not?create?a?new?string?-?it?returns
????//?a?slice?of?the?argument.
????name.split(".").last()
}

fn?main()?{
????let?name?=?"Read?me.?Or?don't.txt";
????if?let?Some(ext)?=?file_ext(name)?{
????????println!("file?extension:?{}",?ext);
????}?else?{
????????println!("no?file?extension");
????}
}

所以,借用規(guī)則也適用它:

fn?main()?{
????let?ext?=?{
????????let?name?=?String::from("Read?me.?Or?don't.txt");
????????file_ext(&name).unwrap_or("")
????????//?error:?`name`?does?not?live?long?enough
????};
????println!("extension:?{:?}",?ext);
}

10 錯(cuò)誤處理

可能失敗的函數(shù)通常返回一個(gè) Result:

fn?main()?{
????let?s?=?std::str::from_utf8(&[240,?159,?141,?137]);
????println!("{:?}",?s);
????//?prints:?Ok("??")

????let?s?=?std::str::from_utf8(&[195,?40]);
????println!("{:?}",?s);
????//?prints:?Err(Utf8Error?{?valid_up_to:?0,?error_len:?Some(1)?})
}

如果你想在失敗的情況下 panic,你可以調(diào)用 unwrap():

fn?main()?{
????let?s?=?std::str::from_utf8(&[240,?159,?141,?137]).unwrap();
????println!("{:?}",?s);
????//?prints:?"??"

????let?s?=?std::str::from_utf8(&[195,?40]).unwrap();
????//?prints:?thread?'main'?panicked?at?'called?`Result::unwrap()`
????//?on?an?`Err`?value:?Utf8Error?{?valid_up_to:?0,?error_len:?Some(1)?}',
????//?src/libcore/result.rs:1165:5
}

或者 .expect(),它可以提供自定義錯(cuò)誤信息。

fn?main()?{
????let?s?=?std::str::from_utf8(&[195,?40]).expect("valid?utf-8");
????//?prints:?thread?'main'?panicked?at?'valid?utf-8:?Utf8Error
????//?{?valid_up_to:?0,?error_len:?Some(1)?}',?src/libcore/result.rs:1165:5
}

或者你也可以使用 match:

fn?main()?{
????match?std::str::from_utf8(&[240,?159,?141,?137])?{
????????Ok(s)?=>?println!("{}",?s),
????????Err(e)?=>?panic!(e),
????}
????//?prints???
}

也可以使用 if let:

fn?main()?{
????if?let?Ok(s)?=?std::str::from_utf8(&[240,?159,?141,?137])?{
????????println!("{}",?s);
????}
????//?prints???
}

或者你可以拋出這樣的錯(cuò)誤:

fn?main()?->?Result<(),?std::str::Utf8Error>?{
????match?std::str::from_utf8(&[240,?159,?141,?137])?{
????????Ok(s)?=>?println!("{}",?s),
????????Err(e)?=>?return?Err(e),
????}
????Ok(())
}

或者你可以使用 ? 來簡(jiǎn)潔地完成它:

fn?main()?->?Result<(),?std::str::Utf8Error>?{
????let?s?=?std::str::from_utf8(&[240,?159,?141,?137])?;
????println!("{}",?s);
????Ok(())
}

操作符 * 可用于解引用,但是訪問字段或調(diào)用方法不需要解引用:

struct?Point?{
????x:?f64,
????y:?f64,
}

fn?main()?{
????let?p?=?Point?{?x:?1.0,?y:?3.0?};
????let?p_ref?=?&p;
????println!("({},?{})",?p_ref.x,?p_ref.y);
}

//?prints?`(1,?3)`

而且你只能在類型為 Copy 的情況下才能這么做:

struct?Point?{
????x:?f64,
????y:?f64,
}

fn?negate(p:?Point)?->?Point?{
????Point?{
????????x:?-p.x,
????????y:?-p.y,
????}
}

fn?main()?{
????let?p?=?Point?{?x:?1.0,?y:?3.0?};
????let?p_ref?=?&p;
????negate(*p_ref);
????//?error:?cannot?move?out?of?`*p_ref`?which?is?behind?a?shared?reference
}
//?now?`Point`?is?`Copy`
#[derive(Clone,?Copy)]
struct?Point?{
????x:?f64,
????y:?f64,
}

fn?negate(p:?Point)?->?Point?{
????Point?{
????????x:?-p.x,
????????y:?-p.y,
????}
}

fn?main()?{
????let?p?=?Point?{?x:?1.0,?y:?3.0?};
????let?p_ref?=?&p;
????negate(*p_ref);?//?...and?now?this?works
}

11 閉包

閉包是 Fn、 FnMut 或 FnOnce 類型的函數(shù),包含一些捕獲的上下文。

它們的參數(shù)是一對(duì)管道(|)中以逗號(hào)分隔的名稱列表。它們不需要大括號(hào),除非您希望有多個(gè)語句。

fn?for_each_planet(f:?F)
????where?F:?Fn(&'static?str)
{
????f("Earth");
????f("Mars");
????f("Jupiter");
}
?
fn?main()?{
????for_each_planet(|planet|?println!("Hello,?{}",?planet));
}

//?prints:
//?Hello,?Earth
//?Hello,?Mars
//?Hello,?Jupiter

借款規(guī)則也適用于它們:

fn?for_each_planet(f:?F)
????where?F:?Fn(&'static?str)
{
????f("Earth");
????f("Mars");
????f("Jupiter");
}
?
fn?main()?{
????let?greeting?=?String::from("Good?to?see?you");
????for_each_planet(|planet|?println!("{},?{}",?greeting,?planet));
????//?our?closure?borrows?`greeting`,?so?it?cannot?outlive?it
}

例如,這樣做不會(huì)奏效:

fn?for_each_planet(f:?F)
????where?F:?Fn(&'static?str)?+?'static?//?`F`?must?now?have?"'static"?lifetime
{
????f("Earth");
????f("Mars");
????f("Jupiter");
}

fn?main()?{
????let?greeting?=?String::from("Good?to?see?you");
????for_each_planet(|planet|?println!("{},?{}",?greeting,?planet));
????//?error:?closure?may?outlive?the?current?function,?but?it?borrows
????//?`greeting`,?which?is?owned?by?the?current?function
}

但這樣可以:

fn?main()?{
????let?greeting?=?String::from("You're?doing?great");
????for_each_planet(move?|planet|?println!("{},?{}",?greeting,?planet));
????//?`greeting`?is?no?longer?borrowed,?it?is?*moved*?into
????//?the?closure.
}

需要可變地借用 FnMut 才能調(diào)用它,因此一次只能調(diào)用它一次。

這是合法的:

fn?foobar(f:?F)
????where?F:?Fn(i32)?->?i32
{
????println!("{}",?f(f(2)));?
}
?
fn?main()?{
????foobar(|x|?x?*?2);
}

//?output:?8

但以下不行:

fn?foobar(mut?f:?F)
????where?F:?FnMut(i32)?->?i32
{
????println!("{}",?f(f(2)));?
????//?error:?cannot?borrow?`f`?as?mutable?more?than?once?at?a?time
}
?
fn?main()?{
????foobar(|x|?x?*?2);
}

不過下面又是合法的:

fn?foobar(mut?f:?F)
????where?F:?FnMut(i32)?->?i32
{
????let?tmp?=?f(2);
????println!("{}",?f(tmp));?
}
?
fn?main()?{
????foobar(|x|?x?*?2);
}

//?output:?8

FnMut 的存在是因?yàn)橐恍╅]包可變地借用了局部變量:

fn?foobar(mut?f:?F)
????where?F:?FnMut(i32)?->?i32
{
????let?tmp?=?f(2);
????println!("{}",?f(tmp));?
}
?
fn?main()?{
????let?mut?acc?=?2;
????foobar(|x|?{
????????acc?+=?1;
????????x?*?acc
????});
}

//?output:?24

這些閉包不能傳遞給期待 Fn 的函數(shù):

fn?foobar(f:?F)
????where?F:?Fn(i32)?->?i32
{
????println!("{}",?f(f(2)));?
}
?
fn?main()?{
????let?mut?acc?=?2;
????foobar(|x|?{
????????acc?+=?1;
????????//?error:?cannot?assign?to?`acc`,?as?it?is?a
????????//?captured?variable?in?a?`Fn`?closure.
????????//?the?compiler?suggests?"changing?foobar
????????//?to?accept?closures?that?implement?`FnMut`"
????????x?*?acc
????});
}

FnOnce 閉包只能調(diào)用一次。它們的存在是因?yàn)橐恍╅]包移出了捕獲時(shí)移動(dòng)的變量:

fn?foobar(f:?F)
????where?F:?FnOnce()?->?String
{
????println!("{}",?f());?
}
?
fn?main()?{
????let?s?=?String::from("alright");
????foobar(move?||?s);
????//?`s`?was?moved?into?our?closure,?and?our
????//?closures?moves?it?to?the?caller?by?returning
????//?it.?Remember?that?`String`?is?not?`Copy`.
}

這是自然地強(qiáng)制執(zhí)行的,因?yàn)?FnOnce 閉包需要移動(dòng)才能被調(diào)用。

以下例子是無效的:

fn?foobar(f:?F)
????where?F:?FnOnce()?->?String
{
????println!("{}",?f());?
????println!("{}",?f());?
????//?error:?use?of?moved?value:?`f`
}

而且,如果你需要有說服力的證明我們的關(guān)閉確實(shí)會(huì)發(fā)生變化,這也是非法的:

fn?main()?{
????let?s?=?String::from("alright");
????foobar(move?||?s);
????foobar(move?||?s);
????//?use?of?moved?value:?`s`
}

不過這樣是正常的:

fn?main()?{
????let?s?=?String::from("alright");
????foobar(||?s.clone());
????foobar(||?s.clone());
}

下面是一個(gè)包含兩個(gè)參數(shù)的閉包:

fn?foobar(x:?i32,?y:?i32,?is_greater:?F)
????where?F:?Fn(i32,?i32)?->?bool
{
????let?(greater,?smaller)?=?if?is_greater(x,?y)?{
????????(x,?y)
????}?else?{
????????(y,?x)
????};
????println!("{}?is?greater?than?{}",?greater,?smaller);
}
?
fn?main()?{
????foobar(32,?64,?|x,?y|?x?>?y);
}

以下是一個(gè)閉包,但忽略了它的兩個(gè)參數(shù):

fn?main()?{
????foobar(32,?64,?|_,?_|?panic!("Comparing?is?futile!"));
}

下面是一個(gè)有點(diǎn)令人擔(dān)憂的閉包:

fn?countdown(count:?usize,?tick:?F)
????where?F:?Fn(usize)
{
????for?i?in?(1..=count).rev()?{
????????tick(i);
????}
}
?
fn?main()?{
????countdown(3,?|i|?println!("tick?{}...",?i));
}

//?output:
//?tick?3...
//?tick?2...
//?tick?1...

下面是一個(gè) toilet 閉包:

fn?main()?{
????countdown(3,?|_|?());
}

之所以這么叫是因?yàn)?|_| () 看起來像個(gè)廁所(toilet )。

任何可迭代的東西都可以在 for in 循環(huán)中使用。

我們剛剛看到一個(gè) range 被使用,但是它也適用于一個(gè) Vec:

fn?main()?{
????for?i?in?vec![52,?49,?21]?{
????????println!("I?like?the?number?{}",?i);
????}
}

或者切片:

fn?main()?{
????for?i?in?&[52,?49,?21]?{
????????println!("I?like?the?number?{}",?i);
????}
}

//?output:
//?I?like?the?number?52
//?I?like?the?number?49
//?I?like?the?number?21

或者是迭代器:

fn?main()?{
????//?note:?`&str`?also?has?a?`.bytes()`?iterator.
????//?Rust's?`char`?type?is?a?"Unicode?scalar?value"
????for?c?in?"rust".chars()?{
????????println!("Give?me?a?{}",?c);
????}
}

//?output:
//?Give?me?a?r
//?Give?me?a?u
//?Give?me?a?s
//?Give?me?a?t

即使迭代的項(xiàng)目被 filter、map 或 flat:

fn?main()?{
????for?c?in?"SuRPRISE?INbOUND"
????????.chars()
????????.filter(|c|?c.is_lowercase())
????????.flat_map(|c|?c.to_uppercase())
????{
????????print!("{}",?c);
????}
????println!();
}

//?output:?UB

你可以從函數(shù)返回一個(gè)閉包:

fn?make_tester(answer:?String)?->?impl?Fn(&str)?->?bool?{
????move?|challenge|?{
????????challenge?==?answer
????}
}

fn?main()?{
????//?you?can?use?`.into()`?to?perform?conversions
????//?between?various?types,?here?`&'static?str`?and?`String`
????let?test?=?make_tester("hunter2".into());
????println!("{}",?test("******"));
????println!("{}",?test("hunter2"));
}

你甚至可以將對(duì)某個(gè)函數(shù)參數(shù)的引用移動(dòng)到它返回的閉包中:

fn?make_tester<'a>(answer:?&'a?str)?->?impl?Fn(&str)?->?bool?+?'a?{
????move?|challenge|?{
????????challenge?==?answer
????}
}

fn?main()?{
????let?test?=?make_tester("hunter2");
????println!("{}",?test("*******"));
????println!("{}",?test("hunter2"));
}

//?output:
//?false
//?true

或者,用省略的生命周期:

fn?make_tester(answer:?&str)?->?impl?Fn(&str)?->?bool?+?'_?{
????move?|challenge|?{
????????challenge?==?answer
????}
}

總結(jié)

以上就是這個(gè) 30 分鐘教程的全部?jī)?nèi)容。作者認(rèn)為,通過以上的學(xué)習(xí),你應(yīng)該能夠閱讀網(wǎng)上找到的大部分 Rust 代碼了。

讀 Rust 代碼和寫 Rust 代碼很不一樣。一方面,你不是讀一個(gè)問題的解決方案,而是實(shí)際解決它;另一方面,Rust 編譯器很強(qiáng)大,可以給你很多幫助。

對(duì)于這篇教程中故意的錯(cuò)誤代碼,Rust 編譯器總是能非常好的提示你,同時(shí)給你很好的建議。

原文鏈接:https://fasterthanli.me/articles/a-half-hour-to-learn-rust

Rust 編程指北編譯,非直接翻譯。

實(shí)話說,這個(gè)教程不可能 30 分鐘學(xué)完,即使學(xué)完了,肯定也沒入門。不過通過這些代碼,自己動(dòng)手實(shí)踐,對(duì)學(xué)習(xí) Rust 還是有幫助的!



推薦閱讀


福利

我為大家整理了一份從入門到進(jìn)階的Go學(xué)習(xí)資料禮包,包含學(xué)習(xí)建議:入門看什么,進(jìn)階看什么。關(guān)注公眾號(hào) 「polarisxu」,回復(fù)?ebook?獲取;還可以回復(fù)「進(jìn)群」,和數(shù)萬 Gopher 交流學(xué)習(xí)。

瀏覽 84
點(diǎn)贊
評(píng)論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)
評(píng)論
圖片
表情
推薦
點(diǎn)贊
評(píng)論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 在线免费观看无码视频| 久久水蜜桃| 97国产精品人人爽人人做| 69久久成人精品| 三级电影久久麻豆| 中文字幕无码在线播放| 亚洲无码人妻| 免费在线观看无码| 精品乱子伦一区二区在线播放| 中文字幕++中文字幕明步| 高清无码三级| 懂色av懂色av粉嫩av无码| 亚洲真人无码| 欧美色图狠狠操| 另类老妇性BBwBBw| 日本免费黄色电影| 欧美疯狂做受XXXXX高潮| 免费91| 国产凹凸视频在线观看| 亚洲AV秘一区二区色盗战流出| 国产精品久久久久野外| 国产无码在线看| 午夜神马影院| 夜间福利视频| 久久天堂一区| 亚洲性夜夜天天天天天天| 欧美一级性爱| 一本道高清| 91人妻人人爽人人澡人人爽| 大香蕉最新视频| 亚洲天堂视频网| 无码一区二区三区四区| 日韩人妻一区二区三区| 国产一a毛一a毛A免费| a一级黄片| 一区二区三区四区| 亚洲中文字幕无码在线观看| 四虎影院中文字幕| 亚洲国产成人精品女人久久久| 欧美日韩免费在线观看| 视频一区二区三区在线观看| 四虎黄色影院| 少妇A片| 豆花视频无码| 亚洲中文字幕日本| 狠狠躁婷婷天天爽综合| 99热在线播放| 国产无码毛片| 大香蕉伊人av| 久草手机视频| 成人AV十八亚洲二区| 国产毛片精品一区二区色欲黄A片| 欧美性受XXXX黑人XYX性爽一| 天天操人人妻| 婷婷色777777| 日本不卡三区| 蜜桃av秘无码一区二区| 亚洲久草| 另类老妇奶BBBBwBB| 综合色亚洲| 男女av免费观看| 国产又爽又黄视频| 午夜福利AV电影| 日韩无码18| 色人阁人妻中文字幕| 三级视频在线播放| 女人毛片| 亚洲九九九九| 影音先锋日韩资源| 日本a片在线观看| 人妻精品在线| 簧片在线免费观看| 密臀久久| 亚洲AA| 五月天三级片| 99久久国产精| 国产一级性爱| 欧美一区二区精品| 午夜福利免费在线观看| 不卡精品| 美女裸体视频网站| 欧美3P视频| 中文字幕不卡AV在线观看| 人人摸人人爱| 69无码| 黄片伊人| 黄网在线看| 欧美成人猛片AAAAAAA| 亚洲成人视频免费观看| 一区二区三区黄色| 欧美精品日韩在线观看| 99久久99久久| 国产精品免费一区二区三区都可以 | 大香蕉在线99| 在线看片国产| 91人妻日韩人妻无码专区精品| 91无码国产| 4虎亚洲人成人网www| 99在线免费视频| 高清一区二区三区| 日韩精品无码一区二区| 日本a在线| 日本三级在线| 天天久久综合| 国产乱子伦日B视频| 黄色视频网站免费| 特一级黄色片| 国产免费无码一区二区| 伊人网视频在线观看| 青娱乐国产在线| 国产一区二区无码| 一区二区三区视频在线观看| 国产精品777| 水蜜桃视频网| 五月网| 伊人大香蕉在线视频| 男女AV| 蜜臀色欲AV无码人妻| 麻豆中文字幕| 91免费观看视频| 日韩人妻无码视频| A在线观看| AV黄片| 在线视频亚洲| 大香蕉75| 国产精品HongKong麻豆| 国产精品无码永久免费A片| 欧美屄视频| 在线观看免费欧美操逼视频| 欧美性爱动态| 中文字幕无码免费| 婷婷色色五月| 无码人妻AⅤ一区二区三区| 日韩香蕉网| A免费在线观看| 欧美性猛交ⅩXXX无码视频 | 国产一区二区不卡| 北条麻妃一区二区三区-免费免费高清观看 | 无码av观看| 人人操夜夜| 成人免费无码A片免费| 无码网站内射| 色九九视频| 国产69视频在线观看| 翔田千里一区二区三区精品播放 | 成人久久久久一级大黄毛片中国| 国产精品揄拍500视频| 国产精品s色| 日韩AV中文字幕在线| 欧美一级黃色A片免费看小优视频| 国产理伦| 成人视频免费网站| 日韩无码久久| aa无码视频| 亚洲无码p| 国产逼逼| 韩国一区二区在线观看| 99久热在线精品| 成人在线三级片| 丁香六月综合激情| 国产精品a久久久久| 日韩va中文字幕无码免费| 黄色AV天堂| 77777免费观看电视剧推荐爱的教育| 国产欧美在线观看| 翔田千里与黑人50分钟| 先锋影音亚洲无码av| 激情五月天在线视频| 亚洲无码三级视频| 69亚洲精品| 无码秘人妻一区二区三-百度| 色五月婷婷综合| 久久午夜福利| 成人三区| 中文字幕一区二区蜜桃| 影音先锋乱伦电影| 日韩免费片| 人妻无码一区二区三区| 国产在线观看免费| 少妇人妻无码| 特级黄色片| 人妻无码| 色欲成人AV| 久久青青草在线视频| 国产精品无码免费| 日韩不卡一区| 国产在线h| 一级A片在线观看| 成人影视亚洲| 国内自拍99| 蜜桃91在线| 亚洲天堂男人天堂| 日韩a片在线观看| 91亚洲精品在线| 黃色A片一级一级一级久别的草原 欧美中文字幕在线观看 | 女人的天堂AV在线观看| 日韩A区| 99热官网| 亚洲无码久久精品| 婷婷三级片| 天天综合国产| 91综合网| 操日视频| 欧美日韩在线观看中文字幕| 老熟妇搡BBBB搡BBBB| 超碰天天爱| h网站在线观看| 极品美女扒开粉嫩小泬高潮一| 欧美男人天堂网| 欧美性猛交XXXX乱大交蜜桃| 免费无码国产在线53| 97在线鲁碰免费视频| 日本一区二区精品| 97精品人妻一区二区三区香蕉| 亚色视频| 99er热精品视频| 懂色av粉嫩AV蜜臀AV| 国产精品尤物| 国产91无码| 黄色综合网| 亚洲午夜视频在线观看| 免费射精一二三区| 在线中文字幕第一页| 三级片亚洲无码| 色热热| 超碰久热| 日本黄A级A片国产免费| 久久电影精品| 可以免费看AV的网站| 中文字幕性爱| 亚洲欧洲久久电影| 亚洲少妇性爱视频| 成人福利在线观看| 狼友在线观看| 亚洲AV无码一区二区三竹菊| 免费观看一级黄片| 欧美日韩人妻| 亚洲天堂一区二区三区| 少妇在线观看| 国产精品2025| 免费网站观看www在线观| 成人无码区免费| 国产91在线视频| 91巨乳| 色噜噜一区二区三区| 亚洲小视频在线| 日韩在线观看| 午夜性爱福利视频| 日产电影一区二区三区| 做爱网| 暗呦罗莉精品一区二区| 一区二区三区四区成人| 91久热| 日韩欧美在线免费观看| 91视频美女内射| 亚洲成人AV| 国产成人免费做爰视频| 91中文字幕在线| 在线A∨视频| 亚洲欧洲无码视频| 7777AV| 国产黄色电影在线观看| 伊人免费视频在线观看| 天堂一区在线观看| 亚洲无码综合| 国产在线观看黄| 亚洲无码婷婷| eeuss一区| 成人电影aaa| 精品丰满人妻一区二区三区免费观| 91污| 手机AV在线| 在线看毛片网站| 美女天天干| 青青草成人在线| 超碰在线日韩| 97国产在线观看| 91久久国产性奴调教| 中文无码日韩| 日韩免费视频一区| 无码一二三四| 99热加勒比| 靠逼网站免费观看| 99免费观看视频| 亚洲字幕在线播放| 噜噜色小说| www.A片| 精品无码一区二区| 久草在在线| 欧美熟妇搡BBBB搡BBBBB| 西西人体大胆ww4444多少集| 久久香蕉人| 啪啪视频在线观看| 操婊网| 国产精品9999| 国产一级特黄大片| 日韩大香蕉在线| 丁香五月在线| 日韩黄色精品| 中国老女人操逼视频| 亚洲视频中文字幕| 日本熟妇无码一区二区| 亚洲中文字幕视频在线观看| 伊人AV在线| 黄色动漫在线免费观看| 国模精品无码一区二区免费蜜桃| 人妻人人干| 做爰视频毛片下载蜜桃视频| 国产乱妇无码毛片A片在线看下载 日韩电影免费在线观看中文字幕 欧美性爱中文字幕 | 久久大香蕉视频| 91大神网址| 91在线无码精品秘入口三人| 中文字幕久久播放| 男女拍拍网站| 久久久一区二区三区四区| 亚洲精品国产精品乱码不卡√香蕉 | www.射| 亚洲精品成AV人片天堂无码 | 都市激情亚洲| 亚洲不卡在线| 免费播放婬乱男女婬视频国产| 亚洲777| 成人自拍电影| 操操日| 俺也去com| 欧美成人在线免费视频| 免费在线观看黄| 欧美成人国产| 日韩人妻无码中文字幕| 在线播放日韩| AV久草| 无码一区二区三区四区| AV日日| 亚洲AV成人片无码网站网蜜柚| 日日騒av无码| 亚洲无码在线视频播放| 国产精品欧美综合在线| 亚洲成人性爱视频| 黃色一级一片免费播放| 日韩不卡一区二区三区| A片在线视频| 大香蕉在线视频观看| 久久久久一| 中文字幕永久在线5| 99reav| 精品无码视频| av手机在线| 四虎黄色| 天堂中文资源在线观看| 成人片在线| 中文字幕日韩无码片| wwwa片| 国产男女性爱视频播放| 不卡视频一区二区三区| 大香蕉国产视频| 大香蕉com| 欧美日韩国产一区| 操b视频在线免费观看| 久久久久久亚洲AV无码专区| 好逼天天操| 欧美超碰在线| 成人一区二区在线| 91精品国产91久久久久久久久久| 最新日韩在线| 亚洲无套内射| 全部免费黄色视频| 国产做受91一片二片老头| 亚洲AV无码成人精品区天堂小说| 波多野结衣高清视频| 大香蕉伊人在线视频| 日本黄色三级| 日韩无码国产精品| 四川少BBB搡BBB爽爽爽| 免费毛片基地| 亚洲AV秘无码不卡在线观看| 免费一级电影| 国产aaaaaaaaaa| 69成人网| 91蝌蚪91九色| 无码超碰| 91看片看婬黄大片女跟女| 成人精品在线观看| 五十路老国产| 日本免费A片| 久久久xxx| 日本黄色片| 操B在线视频| 亚洲无码中文字幕在线观看| 免费观看高清无码| 欧美操逼网| 久久婷婷五月综合伊人| 国产96在线亚洲| 欧美日韩成人在线观看| 99成人在线| 91久久综合| 精品伊人大香蕉| 91成人在线免费视频| 亚洲乱伦视频| 视色视频在线观看| 婷婷午夜福利| 91人人干| 天堂无码高清| 波多野结衣视频在线| 久久久偷拍| 国产美女18毛片水真多| 91国产视频网站| 大鸡巴免费视频| 伊人久久大综合中文无码| 天天弄天天操| 亚洲欧美日韩在线| 91无码精品国产| 草久在线观看| 成人网视频| 真实白嫖91探花无码| 国产三级黄色视频| 色诱AV| 亚洲AV三级片| 欧美一级特黄A片免费看| 青青操原| 污污污www精品国产网站| 欧美另类极品| 综合一区二区| 少妇人妻精品| 色就是欧美| 日韩中文字幕人妻| 亚洲AV电影天堂| 水蜜桃视频在线观看| 日韩一级免费在线观看| 黄色成人视频在线观看| 在线看亚洲| 亚洲中文字幕av| 国产精品免费一区二区三区四区视频 | 99导航| 成人小说在线观看| AV无码网| 色婷婷亚洲精品天天综合| 国产又爽又黄免费网站在| 欧美精品成人免费片| 精品探花| 操一线天逼| 一区二区三区成人电影| 亚洲色图欧美| 日韩操逼片| 人人操人人骑| 日本a片免费| 国产乱视频| 青青草免费在线观看| 轻轻操内射无码| 69pao| 青草久操| 国产强伦轩免费视频在线| 东京热AV在线| 2018天天日天天操| 69视频在线观看| 无码国产高清| 色婷婷亚洲| 91丨九色丨熟女新版| 国产日韩在线视频| 亚洲色人妻| 亚洲欧洲免费视频| 爱爱午夜福利| 超碰在线进入| 成人网| 大鸡巴久久久久久| 91性爱嫩逼视频| 99精品久久久久久无码| 国产一区二区三区四区在线观看| 国产又粗又大又爽91嫩草| 北条麻妃在线一区| 在线观看亚洲无码视频| 黄色电影免费在线观看| 一区二区三区无码高清| 熟妇操逼视频| 狠狠躁日日躁夜夜躁A片无码视频| 色视频在线观看免费| 美女裸体网站国产| 黑人av在线| 无码日韩人妻精品久久蜜桃| 亚洲无码在线高清| 日韩中文字幕av| 色情一级AA片免费观看| 高潮视频在线观看| 69xx视频| 超碰人人搞| 国产激情视频在线| 91在线免费视频观看| 亚洲三级精品| www.黄色视频| 午夜狠狠操| 亚洲色图在线观看| 韩国精品一区二区三区| 91av在线观看视频| 色婷婷AV| 玖玖大香蕉| 国产精品美女在线观看| 亚洲夜夜爱| 91探花视频精选在线播放| 中文字幕日本无码| 很很撸在线视频| 九九久久精品| 伊人综合网站| 99国产综合| 久久久999精品视频| 亚洲91精品| 亚洲天堂男人的天堂| 无码人妻av一区| 欧美成人毛片AAAAAA| 一本色道久久综合亚洲精品小说 | 国产精品偷拍视频| 日本黄色视频免费看| 久久精品一区二区三区蜜芽的特点| 日本精品视频一区二区| 国产艹逼视频| 亚州免费视频| 五月丁香激情在线| 怡春院熟女精品AV| 爱爱视频免费看| 色吧久久| 成人无码99| 亚州无码一区| 中文字幕免费av| 五月天av在线观看| 日韩爱爱视频| 久久嫩草国产成人一区| 欧美午夜影院| 激情五月婷婷色| 一区二区三区不卡视频| 国产一级黄| 免费一区视频| 欧美精品18videosex性欧美 | 国产乱子伦一区二区三区视频| A片网| 免费看的毛片| 成人免费视频网| 一区无码精品| 国产和日韩中文字幕| 国产高清精品软件丝瓜软件| 国产无套免费网站69| 91精品婷婷国产综合| 做aAAAAA免费视频| 性爱无码| 日韩精品电影| 91人人干| 成人黄色免费观看| 激情五月婷婷色| 中文字幕无码播放| www一个人免费观看视频www| 亚洲无码在线播放| 国产毛片毛片毛片| 亚洲第一成网站| 国产免费观看av| 亚洲人人操| 午夜福利在线视频| 七七久久| 婷婷情色| 天天日天天操天天日| 色色婷婷五月天| 国产精品国产精品国产专区| 97久久一区二区| 成人你懂的| 91在线无码精品秘网站| 无码三级片在线观看| 国产亚洲中文字幕| 天天操天天射天天日| 91精品国产一区三一| 久久三级片电影| 巨い巨乳の少妇あジed2k| 四虎精品影院| 久久久穴| 成人午夜在线视频| 欧美激情国产精品| 久久99精品久久久久| 东方美美高清无码一区| 波多野结衣av无码| 草逼电影| 91香蕉视频免费在线观看| 91逼| 操逼黄视频| 91aV视频| 99re这里只有精品6| 精品国产一二三区| 久久黄色成人视频| 屌国产精品| 超碰青娱乐| AV网站在线免费观看| 亚洲人免费视频| 五月丁香成人电影| 中文字幕88页| 国产色婷婷| 亚洲av观看| 亚洲无码一区二区三区| 成年人视频免费看| 九一成人电影| 成人黃色A片免费看| 色老板免费精品无码免费视频| 国产精品国产伦子伦露看| 国产精品欧美7777777| 亚洲电影中文字幕| 逼逼网| AV无码一区二区三区| 日韩无码一| 人妖黃色一級A片| 波多野结衣无码流出| 热逼视频| 亚洲无码动漫| 亲子乱一区二区三区视频| 超碰人人爽| 91无码秘蜜桃一区二区三区-百度| 日韩欧美小电影| 久久久久久久久免费视频| 任你爽在线视频| 色玉米地熟妇| 无码久久| 欧美操逼免费视频| 黑人AV在线播放| 国产精品久久77777| 国产激情综合在线| 国产亚洲无码激情前后夹击| 亚洲AV无码成人精品区www| 91日韩高清| 99免费在线观看视频| 国内精品久久久久久久久久| 综合网操笔| 在线日韩一区二区| 操美女一区二区| 色图在线观看| 亚洲黄色AV| www.麻豆网91成人久久久| 成人在线小视频| 中文字幕不卡在线| aaa无码| 一二三四区视频| 一级在线播放| AV日日| 亚洲第一成年人网站| 乱伦播放五月天| 日皮视频在线观看免费| 中文原创麻豆传媒md0052| 色天使色天堂| 综合站欧美精品| 日韩成人无码| 中国老熟妇| 中文字幕+乱码+中文乱码91| 免费在线黄色电影| 成人H动漫精品一区二区三区蘑菇| 在线免费观看黄色小视频| 高潮国产视频| 白嫩外女BBwBBwBBw| 熟妇女人妻丰满少妇中文字幕| 在线啊啊啊| 日美女网站| 欧美成人性爱视频| 亚洲中文字幕在线视频| 亚洲色婷婷久久精品AV蜜桃| 午夜传媒一区二区三区| 国产手机精品视频| 无码AV一区| 免费无码婬片AAAA片直播| 天堂中文字幕在线观看| 成人一级a片| 三级毛片在线| 国产视频a| 伊人成人在线视频观看| 五月天综合在线| 香蕉在线观看| 国产一级性爱| 一区二区三区四区无码在线| 特黄特色一级特黄大片| 国产福利合集| 超碰毛片| 国产成人精品毛片| 亚洲一级婬片A片AAAA网址| 久99在线视频| 91丨熟女露脸| 亚韩在线| 北岛玲视频在线| 国产特黄级AAAAA片免| 一区二区精品视频| 超碰日| 日韩精品成人在线视频| 欧美裸体视频| 久久久久99| 亚欧黄色| 天堂国产一区二区三区| 亚洲AV无码成人片在线| 国产麻豆传媒| 日韩日韩日韩| 吹潮喷水高潮HD| 日日干AV| 亚洲三级毛片| 国产人妻精品一二三区| 操比视频在线观看| 最新福利视频| 黄色生活片| 爱爱爱免费视频| 91三级片| 91国在线视频| 亚洲人成人无码.www粉色| 中文字幕日韩高清| www.操逼| 日韩在线二区| 国产精品色情A级毛片| 操操操操| 国产日韩欧美91| 日本69AV| a√免费看| 日本成人电影在线观看| 国产剧情91| 欧美XXX视频| 大黑人荫蒂BBBBBBBBB| 日韩高清av| 国产福利精品视频| 日本无码一区二区三区| 在线无码高清| 成人自拍视频| www.zaixianshipin| 午夜啪啪网站| 91久久精品国产91久久公交车| 青青草视频免费在线观看| 亚洲综合99| 欧美午夜激情视频| 色色色欧美| 成人动漫在线观看| 成人免看一级a一片A片| 亚洲色情在线观看| 天天操中文字幕| 中文字幕一区二区无码成人| 屌国产精品| 午夜福利影院在线| 很很撸在线视频| 超碰人人爱人人操| 国产人体视频| 三级片视频网址| 久久国产99| 亚洲一级AV| 91九九九| 中文资源在线a中文| 国产三级视频| 国产成人精品麻豆| 久久久久9999| 俺也来最新色视频| 91在线精品一区二区| 三级操逼| 一插综合网| 91人妻视频| 黄色成人网址| 91一级特黄大片| 超碰在线观看免费| 黄片高清无码| 操逼网站免费| 国产口爆| 黄色亚洲无码| 国产噜噜噜噜噜久久久久久久久| 亚洲AV无码乱码国产| 3d动漫一区二区| 黄色高清无码| 日韩欧美在线视频观看| 天天色天天日| 爱视频福利网| 91精品国产乱码久久久久| 亚洲二区视频| 大香蕉大香蕉视频网| 一区二区三区视频在线| 加勒比无码高清| 中文字幕AV在线播放| 四虎无码丰满人妻| 婷婷视频导航| 亚洲熟妇AV日韩熟妇在线| 一级特黄妇女高潮AA片免费播放 | 激情五月毛片| 无码三级在线播放| 成人AV在线资源| 俺来也在线视频| 亚洲小说区图片区| 日韩电影一区| 最美孕交vivoestv另类| 688AV秘无码一区二区| 亚洲AV秘无码不卡在线观看| 欧美一卡| 久操视频在线免费观看| 先锋影音在线资源| 欧美日韩成人在线观看| 国产美女操逼网站| 极品少妇AV| 天堂中文资源在线观看| 色综合久久88色综合天天99| 在线观看无码高清视频| 黄色小电影在线观看| 亚洲国产色婷婷| 亚洲精品a| 精品成人影视| 久久黄色视屏| 日韩爱爱免费视频| 日韩福利电影| 国产精品资源| 性欧美XXXX| 日本一级特级毛片视频| 插逼视频网站| 三级三级久久三级久久18| 亚洲AV在线观看| 毛片网站大全| 人人摸在线视频| 久久久久久久久久国产| 香蕉操逼视频| 欧美日韩一区二区三区| 欧美黄色免费| 日本老女人视频| 97人妻天天摸天天爽天天| 日韩无码一二三| 狼友视频报放| 天天色人人| 天天日比| 俺来也俺也啪WWW色| 日本久久网| 91精品国产闺蜜国产在线闺蜜| 一边做一边说国语对白| 免费观看一区二区三区| 国产精品99久久久久的广告情况| 一级调教看片| 午夜成人无码视频| 日韩大香蕉网| 免费一级做a爱片毛片A片小说| 91视频一区| 99精品一区二区三区| 人妻黑人一区二区三区| 97人人射| 日韩91视频| 99久久久久久久无码| 免费在线观看AV网站| 色婷婷日韩精品一区二区三区| 亚洲成人三区| 欧一美一婬一伦一区二区三区自慰| 日韩一区不卡| 国产一级婬乱片免费| 免费观看黄色视频| 黄色三级毛片| 91精品视频网| 人人看人人搞人人摸| 蜜桃Av噜噜一区二区| 亚洲AV永久无码成人| 国产精品免费人成网站酒店| 人人操超碰| 国产综合激情| 成人av网站在线播放| 欧美大鸡巴在线观看| 老妇槡BBBB槡BBBB槡| 超碰乱伦| 亚洲高清无码播放| 无码一区二区高清| 国产91探花秘入口| 91精品国产91久久久久久久久久| 成人无码区免费AV毛片| 欧美日韩国产成人| 大荫蒂精品另类| 18禁无码网站| 黄片视频在线免费观看| 日韩操逼电影| 欧美日本色| 免费观看黄色视频| 国产精品久久久久野外| 欧美激情网| 国产精品操逼视频| 精品乱子伦一区二区三区免费播放| 永久免费无码中文字幕| 精品成人在线视频| 免费在线观看Av| 一牛影视精品av| 小早川怜子精品一区二区| 丁香五月少妇| 亚洲麻豆| 97精品人妻| 一级免费黄色片| 搡BBBB| 亲子乱AⅤ一区二区三区| 日韩欧美中文在线| 在线国产小视频| 免费黄片网站在线观看| 欧美精品一卡| 黄片视频国产| NP玩烂了公用爽灌满视频播放| 97超碰人人摸| 国产一级A片免费播放| 开心五月色婷婷综合开心网| 豆花无码视频一区二区| 韩国成人无码视频| 日韩欧美视频一区国产欧美在线 | 无码高清免费| 日韩麻豆| 国产色综合视频| 人人草人人操| a视频| 日本黄色视| 美女网站在线观看| 日本a在线观看| 天天撸一撸视频| 免费中文字幕av| 无码专区中文字幕| 天堂在线8| 粉嫩99精品99久久久久| 黄av在线|