一坤次、簡介
????Rust是Mozilla公司推出的一門全新的編程語言凿可,1.0版本于2015年5月15日正式對外發(fā)布。作為多年來少有的新一代系統(tǒng)及編程語言术裸,它的設(shè)計準(zhǔn)則是“安全、并發(fā)亭枷、實用”袭艺。他的設(shè)計者是這樣定位這門語言的:Rust的設(shè)計目標(biāo)是要做一門系統(tǒng)編程語言,運行性能高叨粘、避免幾乎所有的段錯(Segmentation Fault)和保證線程安全(Thread Safety)猾编。這意味著Rust可以用于建造高效可靠的系統(tǒng)。
1升敲、安全
? ??????Rust最重要的特點就是能提供內(nèi)存安全保證答倡,而且沒有額外的性能損失。在傳統(tǒng)的系統(tǒng)及編程語言(C/C++)的開過程中冻晤,經(jīng)常出現(xiàn)因各種內(nèi)存錯誤引起的崩潰或BUG苇羡,比如空指針、野指針鼻弧、內(nèi)存泄漏设江、內(nèi)存越界、段錯誤攘轩、數(shù)據(jù)競爭叉存、迭代器失效等。鑒于手動內(nèi)存管理非常容易出問題度帮,因而發(fā)明了垃圾回收機(jī)制(Garbage collection),但是不管使用哪種算法的GC系統(tǒng)歼捏,都會在性能上付出較大的代價。要么需要較大的運行時占用較大內(nèi)存笨篷,要么需要暫停整個程序瞳秽,要么具備不確定性的時延。Rust對自己的定位是接近芯片硬件的系統(tǒng)級編程語言率翅。因此练俐,他不可能選擇使用自動垃圾回收的機(jī)制來解決問題。事實證明冕臭,要想解決內(nèi)存安全的問題腺晾,小修小補(bǔ)是不夠的燕锥,必須搞清楚導(dǎo)致內(nèi)存錯誤的根本原因。從源頭上解決悯蝉。Rust就是為此而生的归形。
2、并發(fā)
? ??????在計算機(jī)單核性能越來越接近瓶頸的今天鼻由,多核并行成了提高軟件執(zhí)行效率的發(fā)展趨勢暇榴。一些編程語言已經(jīng)開始從語言層面支持并發(fā)編程,把“并發(fā)”的概念植入到了編程語言的血液中蕉世。然而跺撼,在傳統(tǒng)的系統(tǒng)級編程語言中,并行代碼很容易出錯讨彼,而且有些問題很難復(fù)現(xiàn),難以發(fā)現(xiàn)和解決問題柿祈,debug的成本非常高哈误。線程安全問題一直以來都是非常令人頭痛的問題。Rust當(dāng)然也不會在這一重要領(lǐng)域落伍躏嚎,它也非常好地支持了并發(fā)編程蜜自。更重要的是,在強(qiáng)大的內(nèi)存安全特性的支持下卢佣,Rust一舉解決了并發(fā)條件下的數(shù)據(jù)競爭(Data Race)問題重荠。它從編譯階段就將數(shù)據(jù)競爭解決在了萌芽狀態(tài),保障了線程安全虚茶。Rust在并發(fā)方面還具有相當(dāng)不錯的可擴(kuò)展性戈鲁。所有跟線程安全相關(guān)的特性,都不是在編譯器中寫死的嘹叫。用戶可以用庫的形式實現(xiàn)各種高效且安全的并發(fā)編程模型婆殿,進(jìn)而充分利用多核時代的硬件性能。
3罩扇、實用
? ??????Rust并不只是實驗室中的研究型產(chǎn)品婆芦,它的目標(biāo)是解決目前軟件行業(yè)中實實在在的各種問題。它的實用性體現(xiàn)在方方面面喂饥。Rust編譯器的后端是基于著名的LLVM完成機(jī)器碼生成和優(yōu)化的消约,它只需要一個非常小巧的運行時即可工作,執(zhí)行效率上可與C語言相媲美员帮,具備很好的跨平臺特性或粮。Rust擯棄了手動內(nèi)存管理帶來的各種不安全的弊端,同時也避免了自動垃圾回收帶來的效率損失和不可控性集侯。在絕大部分情況下被啼,保持了“無額外性能損失”的抽象能力帜消。Rust具備比較強(qiáng)大的類型系統(tǒng),借鑒了許多現(xiàn)代編程語言的歷史經(jīng)驗浓体,包含了眾多方便“的語法特性泡挺。其中包括代數(shù)類型系統(tǒng)、模式匹配命浴、閉包娄猫、生成器、類型推斷生闲、泛型媳溺、與C庫ABI兼容、宏碍讯、模塊管理機(jī)制悬蔽、內(nèi)置開源庫發(fā)布和管理機(jī)制、支持多種編程范式等捉兴。它吸收了許多其他語言中優(yōu)秀的抽象能力蝎困,海納百川,兼容并蓄倍啥。在不影響安全和效率的情況下禾乘,擁有不俗的抽象表達(dá)力。
二虽缕、Rust安裝
可以根據(jù)不同平臺(Linux始藕、macOS、Windows?)參照Rust官方文檔的安裝方式氮趋,進(jìn)行安裝和設(shè)置環(huán)境變量伍派。
Rust官方文檔鏈接:https://doc.rust-lang.org/1.30.0/book/2018-edition/ch01-01-installation.html
中文版安裝教程:https://rustlang-cn.org/users/book-exp/01%20Getting%20Started/01%20Getting%20Started.html
安裝完畢,可采用以下命令驗證凭峡,能顯示出Rust版本即為安裝成功:
$ rustc --version 或 $rustup show
第一個Rust程序——Hello world
首先創(chuàng)建一個存放 Rust 代碼的目錄拙已。并將你的所有項目存放在這里。
打開終端并輸入如下命令創(chuàng)建?projects?目錄摧冀,并在?projects?目錄中為 Hello, world! 項目創(chuàng)建一個目錄倍踪。
對于 Linux 和 macOS,輸入:
$ mkdir ~/projects
$ cd ~/projects
$ mkdir hello_world
$ cd hello_world
編寫并運行 Rust 程序
接下來索昂,新建一個源文件建车,命名為?main.rs。Rust 源文件總是以?.rs?擴(kuò)展名結(jié)尾椒惨。如果文件名包含多個單詞缤至,使用下劃線分隔它們。例如命名為?hello_world.rs康谆,而不是?helloworld.rs领斥。
現(xiàn)在打開剛創(chuàng)建的?main.rs?文件嫉到,輸入示例 1-1 中的代碼。
fn main() {
????println!("Hello, world!");
}
保存月洛,進(jìn)入終端輸入命令rustc hello_world.rs編譯,編譯完成后輸入./main運行程序
終端將會打印出 Hello何恶,world!
三、編輯器
????????Rust IDE可以根據(jù)個人喜好采用vim嚼黔、emacs细层、vscode、atom唬涧、sublime疫赎、Visual Studio等,我個人比較喜歡IntelliJ IDEA和Visual Studio.
四碎节、Rust語言基礎(chǔ)
(一)通用編程概念 Common Programming Concepts
1捧搞、關(guān)鍵字keywords
Rust 語言有一組保留的?關(guān)鍵字(keywords),就像大部分語言一樣狮荔,它們只能由語言本身使用实牡。記住,你不能使用這些關(guān)鍵字作為變量或函數(shù)的名稱轴合。大部分關(guān)鍵字有特殊的意義,你將在 Rust 程序中使用它們完成各種任務(wù)碗短;一些關(guān)鍵字目前沒有相應(yīng)的功能受葛,是為將來可能添加的功能保留的≠怂可以在附錄 A 中找到關(guān)鍵字的列表总滩。
2、標(biāo)識符identifier
這里我們將對本書中的一些概念做一些解釋:變量巡雨、函數(shù)闰渔、結(jié)構(gòu)體等等。所有這些都需要名稱铐望。Rust 中的名稱被稱為 “標(biāo)識符”(“identifier”)冈涧,它們可以是任意非空的 ASCII 字符串,不過有如下限制:
要么是:
第一個字符是字母正蛙。
其它字符是字母數(shù)字或者 _督弓。
或者是:
第一個字符是 _逻锐。
標(biāo)識符需多于一個字符烁挟。單獨的 _ 不是標(biāo)識符。
其它字符是字母數(shù)字或者 _踏揣。
3锻全、原始標(biāo)識符raw identifier
????????有時出于某種原因你可能需要將關(guān)鍵字作為名稱狂塘。比如你需要調(diào)用 C 語言庫中名為?match?的函數(shù)录煤,在 C 語言中?match?不是關(guān)鍵字。為此你可以使用 “原始標(biāo)識符”(“raw identifier”)荞胡。原始標(biāo)識符以?r#?開頭:
let r#fn = "this variable is named 'fn' even though that's a keyword";
// 調(diào)用名為 'match' 的函數(shù)
r#match();
你無需經(jīng)常用到原始標(biāo)識符妈踊,但是當(dāng)你?真正?需要它們時可以這么做。
(二)變量與可變性 Variables and Mutability
????????變量默認(rèn)是不可改變的(immutable)硝训。這是推動你以充分利用 Rust 提供的安全性和簡單并發(fā)性來編寫代碼的眾多方式之一响委。不過,你仍然可以使用可變變量窖梁。讓我們探討一下 Rust 擁抱不可變性的原因及方法赘风,以及何時你不想使用不可變性。當(dāng)變量不可變時纵刘,一旦值被綁定一個名稱上邀窃,你就不能改變這個值。
1假哎、變量和常量的區(qū)別
????????不允許改變值的變量瞬捕,可能會使你想起另一個大部分編程語言都有的概念:常量(constants)。類似于不可變變量舵抹,常量是綁定到一個名稱的不允許改變的值肪虎,不過常量與變量還是有一些區(qū)別。
????????首先惧蛹,不允許對常量使用?mut扇救。常量不光默認(rèn)不能變,它總是不能變香嗓。聲明常量使用?const?關(guān)鍵字而不是?let迅腔,并且必須注明值的類型。常量可以在任何作用域中聲明靠娱,包括全局作用域沧烈,這在一個值需要被很多部分的代碼用到時很有用。最后一個區(qū)別是像云,常量只能被設(shè)置為常量表達(dá)式锌雀,而不能是函數(shù)調(diào)用的結(jié)果,或任何其他只能在運行時計算出的值迅诬。
2汤锨、隱藏(Shadowing)
? ? ? 我們可以定義一個與之前變量同名的新變量,而新變量會?隱藏?之前的變量百框。Rustacean 們稱之為第一個變量被第二個?隱藏?了闲礼,這意味著使用這個變量時會看到第二個值。可以用相同變量名稱來隱藏一個變量柬泽,以及重復(fù)使用?let?關(guān)鍵字來多次隱藏慎菲。
????????隱藏與將變量標(biāo)記為?mut?是有區(qū)別的。當(dāng)不小心嘗試對變量重新賦值時锨并,如果沒有使用?let?關(guān)鍵字露该,就會導(dǎo)致編譯時錯誤。通過使用?let第煮,我們可以用這個值進(jìn)行一些計算解幼,不過計算完之后變量仍然是不變的。
mut?與隱藏的另一個區(qū)別是包警,當(dāng)再次使用?let?時撵摆,實際上創(chuàng)建了一個新變量,我們可以改變值的類型害晦,但復(fù)用這個名字特铝。例如,假設(shè)程序請求用戶輸入空格字符來說明希望在文本之間顯示多少個空格壹瘟,然而我們真正需要的是將輸入存儲成數(shù)字(多少個空格):
letspaces = "? ? ? ? ?";
letspaces = spaces.len();
(三)數(shù)據(jù)類型 Data Types
????????在 Rust 中鲫剿,每一個值都屬于某一個?數(shù)據(jù)類型(data type),這告訴 Rust 它被指定為何種數(shù)據(jù)稻轨,以便明確數(shù)據(jù)處理方式灵莲。我們將看到兩類數(shù)據(jù)類型子集:標(biāo)量(scalar)和?復(fù)合(compound)。記住殴俱,Rust 是?靜態(tài)類型(statically typed)語言笆呆,也就是說在編譯時就必須知道所有變量的類型。根據(jù)值及其使用方式粱挡,編譯器通常可以推斷出我們想要用的類型俄精。當(dāng)多種類型均有可能時询筏,比如第二章的 “比較猜測的數(shù)字和秘密數(shù)字” 使用?parse?將?String?轉(zhuǎn)換為數(shù)字時,必須增加類型注解
1竖慧、標(biāo)量類型
標(biāo)量(scalar)類型代表一個單獨的值嫌套。Rust 有四種基本的標(biāo)量類型:整型、浮點型圾旨、布爾類型和字符類型踱讨。你可能在其他語言中見過它們。讓我們深入了解它們在 Rust 中是如何工作的砍的。
1.1整型
整數(shù)?是一個沒有小數(shù)部分的數(shù)字痹筛。我們在第二章使用過?u32?整數(shù)類型。該類型聲明表明,它關(guān)聯(lián)的值應(yīng)該是一個占據(jù) 32 比特位的無符號整數(shù)(有符號整數(shù)類型以?i?開頭而不是?u)帚稠。表格 3-1 展示了 Rust 內(nèi)建的整數(shù)類型谣旁。在有符號列和無符號列中的每一個變體(例如,i16)都可以用來聲明整數(shù)值的類型滋早。
表格 3-1: Rust 中的整型
長度? ?有符號 無符號
8-bit? ? ? i8? ? ? ? u8
16-bit? ? i16? ? ? u16
32-bit? ? i32? ? ? u32
64-bit? ? i64? ? ? u64
????????每一個變體都可以是有符號或無符號的榄审,并有一個明確的大小。有符號?和?無符號?代表數(shù)字能否為負(fù)值杆麸,換句話說搁进,數(shù)字是否需要有一個符號(有符號數(shù)),或者永遠(yuǎn)為正而不需要符號(無符號數(shù))昔头。這有點像在紙上書寫數(shù)字:當(dāng)需要考慮符號的時候饼问,數(shù)字以加號或減號作為前綴;然而减细,可以安全地假設(shè)為正數(shù)時匆瓜,加號前綴通常省略。有符號數(shù)以補(bǔ)碼形式(two’s complement representation)存儲(如果你不清楚這是什么未蝌,可以在網(wǎng)上搜索驮吱;對其的解釋超出了本書的范疇)。
????????每一個有符號的變體可以儲存包含從 -(2n - 1) 到 2n - 1?- 1 在內(nèi)的數(shù)字萧吠,這里?n?是變體使用的位數(shù)左冬。所以?i8?可以儲存從 -(27) 到 27?- 1 在內(nèi)的數(shù)字,也就是從 -128 到 127纸型。無符號的變體可以儲存從 0 到 2n?- 1 的數(shù)字拇砰,所以?u8?可以儲存從 0 到 28?- 1 的數(shù)字,也就是從 0 到 255狰腌。
????????另外除破,isize?和?usize?類型依賴運行程序的計算機(jī)架構(gòu):64 位架構(gòu)上它們是 64 位的, 32 位架構(gòu)上它們是 32 位的琼腔。
????????可以使用表格 3-2 中的任何一種形式編寫數(shù)字字面值瑰枫。注意除 byte 以外的所有數(shù)字字面值允許使用類型后綴,例如?57u8丹莲,同時也允許使用?_?做為分隔符以方便讀數(shù)光坝,例如1_000。
表格 3-2: Rust 中的整型字面值
數(shù)字字面值例子
Decimal? 98_222
Hex? 0xff
Octal? 0o77
Binary? 0b1111_0000
Byte (u8?only)? b'A'
那么該使用哪種類型的數(shù)字呢甥材?如果拿不定主意盯另,Rust 的默認(rèn)類型通常就很好,數(shù)字類型默認(rèn)是?i32:它通常是最快的洲赵,甚至在 64 位系統(tǒng)上也是鸳惯。isize?或?usize?主要作為某些集合的索引商蕴。
整型溢出
比方說有一個?u8?,它可以存放從零到?255?的值悲敷。那么當(dāng)你將其修改為?256?時會發(fā)生什么呢究恤?這被稱為 “整型溢出”(“integer overflow” ),關(guān)于這一行為 Rust 有一些有趣的規(guī)則后德。當(dāng)在 debug 模式編譯時部宿,Rust 檢查這類問題并使程序?panic,這個術(shù)語被 Rust 用來表明程序因錯誤而退出瓢湃。第九章會詳細(xì)介紹 panic理张。
在 release 構(gòu)建中,Rust 不檢測溢出绵患,相反會進(jìn)行一種被稱為 “two’s complement wrapping” 的操作雾叭。簡而言之,256?變成?0落蝙,257?變成?1织狐,依此類推。依賴溢出被認(rèn)為是一種錯誤筏勒,即便可能出現(xiàn)這種行為移迫。如果你確實需要這種行為,標(biāo)準(zhǔn)庫中有一個類型顯式提供此功能管行,Wrapping厨埋。
1.2 浮點型
????????Rust 也有兩個原生的?浮點數(shù)(floating-point numbers)類型,它們是帶小數(shù)點的數(shù)字捐顷。Rust 的浮點數(shù)類型是?f32?和?f64荡陷,分別占 32 位和 64 位。默認(rèn)類型是?f64迅涮,因為在現(xiàn)代 CPU 中废赞,它與?f32?速度幾乎一樣,不過精度更高叮姑。
這是一個展示浮點數(shù)的實例:
文件名: src/main.rs
fnmain(){letx=2.0;// f64lety:f32=3.0;// f32}
浮點數(shù)采用 IEEE-754 標(biāo)準(zhǔn)表示唉地。f32?是單精度浮點數(shù),f64?是雙精度浮點數(shù)戏溺。
1.3 數(shù)值運算
Rust 中的所有數(shù)字類型都支持基本數(shù)學(xué)運算:加法、減法屠尊、乘法旷祸、除法和取余。下面的代碼展示了如何在?let?語句中使用它們:
文件名: src/main.rs
fnmain(){// 加法letsum=5+10;// 減法letdifference=95.5-4.3;// 乘法letproduct=4*30;// 除法letquotient=56.7/32.2;// 取余l(xiāng)etremainder=43%5;}
這些語句中的每個表達(dá)式使用了一個數(shù)學(xué)運算符并計算出了一個值讼昆,然后綁定給一個變量托享。附錄 B 包含 Rust 提供的所有運算符的列表。
1.4 布爾型
????????正如其他大部分編程語言一樣,Rust 中的布爾類型有兩個可能的值:true?和?false闰围。Rust 中的布爾類型使用?bool?表示赃绊。例如:
文件名: src/main.rs
fnmain(){lett=true;letf:bool=false;// 顯式指定類型注解}
使用布爾值的主要場景是條件表達(dá)式,例如?if?表達(dá)式羡榴。在 “控制流”(“Control Flow”)部分將介紹?if?表達(dá)式在 Rust 中如何工作碧查。
1.5 字符類型
????????目前為止只使用到了數(shù)字,不過 Rust 也支持字母校仑。Rust 的?char?類型是語言中最原生的字母類型忠售,如下代碼展示了如何使用它。(注意?char?由單引號指定迄沫,不同于字符串使用雙引號稻扬。)
文件名: src/main.rs
fnmain(){letc='z';letz='?';letheart_eyed_cat='??';}
????????Rust 的?char?類型代表了一個 Unicode 標(biāo)量值(Unicode Scalar Value),這意味著它可以比 ASCII 表示更多內(nèi)容羊瘩。在 Rust 中泰佳,拼音字母(Accented letters),中文尘吗、日文逝她、韓文等字符,emoji(繪文字)以及零長度的空白字符都是有效的?char?值摇予。Unicode 標(biāo)量值包含從?U+0000?到?U+D7FF?和?U+E000到?U+10FFFF?在內(nèi)的值汽绢。不過,“字符” 并不是一個 Unicode 中的概念侧戴,所以人直覺上的 “字符” 可能與 Rust 中的?char?并不符合宁昭。第八章的 “字符串” 中將詳細(xì)討論這個主題。
2酗宋、復(fù)合類型
復(fù)合類型(Compound types)可以將多個值組合成一個類型积仗。Rust 有兩個原生的復(fù)合類型:元組(tuple)和數(shù)組(array)。
2.1 元組類型
元組是一個將多個其他類型的值組合進(jìn)一個復(fù)合類型的主要方式蜕猫。
我們使用包含在圓括號中的逗號分隔的值列表來創(chuàng)建一個元組寂曹。元組中的每一個位置都有一個類型,而且這些不同值的類型也不必是相同的回右。這個例子中使用了可選的類型注解:
文件名: src/main.rs
fnmain(){lettup:(i32,f64,u8)=(500,6.4,1);}
tup?變量綁定到整個元組上隆圆,因為元組是一個單獨的復(fù)合元素。為了從元組中獲取單個值翔烁,可以使用模式匹配(pattern matching)來解構(gòu)(destructure)元組值渺氧,像這樣:
文件名: src/main.rs
fnmain(){lettup=(500,6.4,1);let(x,y,z)=tup;println!("The value of y is: {}",y);}
程序首先創(chuàng)建了一個元組并綁定到?tup?變量上。接著使用了?let?和一個模式將?tup?分成了三個不同的變量蹬屹,x侣背、y?和?z白华。這叫做?解構(gòu)(destructuring),因為它將一個元組拆成了三個部分贩耐。最后弧腥,程序打印出了?y?的值,也就是?6.4潮太。
除了使用模式匹配解構(gòu)外管搪,也可以使用點號(.)后跟值的索引來直接訪問它們。例如:
文件名: src/main.rs
```
fn main() {
????let x:(i32,f64,u8) = (500,6.4,1);
????let five_hundred = x.0;
????let six_point_four = x.1;
????let one=x.2;
}
```
這個程序創(chuàng)建了一個元組消别,x抛蚤,并接著使用索引為每個元素創(chuàng)建新變量。跟大多數(shù)編程語言一樣寻狂,元組的第一個索引值是 0岁经。
2.2 數(shù)組類型
????????另一個包含多個值的方式是?數(shù)組(array)。與元組不同蛇券,數(shù)組中的每個元素的類型必須相同缀壤。Rust 中的數(shù)組與一些其他語言中的數(shù)組不同,因為 Rust 中的數(shù)組是固定長度的:一旦聲明纠亚,它們的長度不能增長或縮小塘慕。
Rust 中,數(shù)組中的值位于中括號內(nèi)的逗號分隔的列表中:
文件名: src/main.rs
fn main() {
????leta=[1,2,3,4,5];
}
當(dāng)你想要在棧(stack)而不是在堆(heap)上為數(shù)據(jù)分配空間(第四章將討論棧與堆的更多內(nèi)容)蒂胞,或者是想要確蓖寄兀總是有固定數(shù)量的元素時,數(shù)組非常有用骗随。但是數(shù)組并不如 vector 類型靈活蛤织。vector 類型是標(biāo)準(zhǔn)庫提供的一個?允許?增長和縮小長度的類似數(shù)組的集合類型。當(dāng)不確定是應(yīng)該使用數(shù)組還是 vector 的時候鸿染,你可能應(yīng)該使用 vector指蚜。第八章會詳細(xì)討論 vector。
一個你可能想要使用數(shù)組而不是 vector 的例子是涨椒,當(dāng)程序需要知道一年中月份的名字時摊鸡。程序不大可能會去增加或減少月份。這時你可以使用數(shù)組蚕冬,因為我們知道它總是包含 12 個元素:
let months=["January","February","March","April","May","June","July","August","September","October","November","December"];
數(shù)組的類型比較有趣免猾;它看起來像?[type; number]。例如:
leta:[i32;5]=[1,2,3,4,5];
首先是方括號囤热;這看起來像創(chuàng)建數(shù)組的語法猎提。其中有兩部分由分號分割的信息。第一部分是數(shù)組中每個元素的類型赢乓。因為所有元素都是相同類型的忧侧,所以只需列出一次。分號之后牌芋,是一個表示數(shù)組長度的數(shù)字蚓炬。因為數(shù)組是固定長度的,該數(shù)字也一直保持不變躺屁,即便數(shù)組的元素被修改肯夏,它也不會增長或縮小。
2.3 訪問數(shù)組元素
數(shù)組是一整塊分配在棧上的內(nèi)存犀暑⊙被鳎可以使用索引來訪問數(shù)組的元素,像這樣:
文件名: src/main.rs
fn main() {
let a = [1,2,3,4,5];
let first = a[0];
let second = a[1];
}
在這個例子中耐亏,叫做?first?的變量的值是?1徊都,因為它是數(shù)組索引?[0]?的值。變量?second?將會是數(shù)組索引?[1]?的值?2广辰。
2.4 無效的數(shù)組元素訪問
????????如果我們訪問數(shù)組結(jié)尾之后的元素會發(fā)生什么呢暇矫?比如你將上面的例子改成下面這樣,這可以編譯不過在運行時會因錯誤而退出:
文件名: src/main.rs
fn main() {
? ? let a = [1, 2, 3, 4, 5];
? ? let index = 10;
? ? let element = a[index];
? ? println!("The value of element is: {}", element);
}
使用?cargo run?運行代碼后會產(chǎn)生如下結(jié)果:
$ cargo run
? Compiling arrays v0.1.0 (file:///projects/arrays)
? ? Finished dev [unoptimized + debuginfo] target(s) in 0.31 secs
? ? Running `target/debug/arrays`
thread '<main>' panicked at 'index out of bounds: the len is 5 but the index is
10', src/main.rs:6
note: Run with `RUST_BACKTRACE=1` for a backtrace.
????????編譯并沒有產(chǎn)生任何錯誤择吊,不過程序會出現(xiàn)一個?運行時(runtime)錯誤并且不會成功退出李根。當(dāng)嘗試用索引訪問一個元素時,Rust 會檢查指定的索引是否小于數(shù)組的長度几睛。如果索引超出了數(shù)組長度房轿,Rust 會?panic,這是 Rust 術(shù)語所森,它用于程序因為錯誤而退出的情況囱持。
????????這是第一個在實戰(zhàn)中遇到的 Rust 安全原則的例子。在很多底層語言中必峰,并沒有進(jìn)行這類檢查洪唐,這樣當(dāng)提供了一個不正確的索引時,就會訪問無效的內(nèi)存吼蚁。通過立即退出而不是允許內(nèi)存訪問并繼續(xù)執(zhí)行凭需,Rust 讓你避開此類錯誤。第九章會討論更多 Rust 的錯誤處理肝匆。
(四)函數(shù) Function
????????函數(shù)遍布于 Rust 代碼中粒蜈。你已經(jīng)見過語言中最重要的函數(shù)之一:main?函數(shù),它是很多程序的入口點旗国。你也見過?fn?關(guān)鍵字枯怖,它用來聲明新函數(shù)。
????????Rust 代碼中的函數(shù)和變量名使用?snake case?規(guī)范風(fēng)格能曾。在 snake case 中度硝,所有字母都是小寫并使用下劃線分隔單詞肿轨。
1、 函數(shù)參數(shù)
????????函數(shù)也可以被定義為擁有?參數(shù)(parameters)蕊程,參數(shù)是特殊變量椒袍,是函數(shù)簽名的一部分。當(dāng)函數(shù)擁有參數(shù)(形參)時藻茂,可以為這些參數(shù)提供具體的值(實參)驹暑。技術(shù)上講,這些具體值被稱為參數(shù)(arguments)辨赐,但是在日常交流中优俘,人們傾向于不區(qū)分使用?parameter?和?argument?來表示函數(shù)定義中的變量或調(diào)用函數(shù)時傳入的具體值。
2掀序、 包含語句和表達(dá)式的函數(shù)體
? ? ? ?函數(shù)體由一系列的語句和一個可選的結(jié)尾表達(dá)式構(gòu)成帆焕。目前為止,我們只介紹了沒有結(jié)尾表達(dá)式的函數(shù)不恭,不過你已經(jīng)見過作為語句一部分的表達(dá)式视搏。因為 Rust 是一門基于表達(dá)式(expression-based)的語言,這是一個需要理解的(不同于其他語言)重要區(qū)別县袱。其他語言并沒有這樣的區(qū)別浑娜,所以讓我們看看語句與表達(dá)式有什么區(qū)別以及這些區(qū)別是如何影響函數(shù)體的。實際上式散,我們已經(jīng)使用過語句和表達(dá)式筋遭。語句(Statements)是執(zhí)行一些操作但不返回值的指令。表達(dá)式(Expressions)計算并產(chǎn)生一個值暴拄。
3漓滔、具有返回值的函數(shù)
????????函數(shù)可以向調(diào)用它的代碼返回值。我們并不對返回值命名乖篷,但要在箭頭(->)后聲明它的類型响驴。在 Rust 中,函數(shù)的返回值等同于函數(shù)體最后一個表達(dá)式的值撕蔼。使用?return?關(guān)鍵字和指定值豁鲤,可從函數(shù)中提前返回;但大部分函數(shù)隱式的返回最后的表達(dá)式鲸沮。
(五)注釋 Comments
????????所有程序員都力求使其代碼易于理解琳骡,不過有時還需要提供額外的解釋。在這種情況下讼溺,程序員在源碼中留下記錄楣号,或者?注釋(comments),編譯器會忽略它們,不過閱讀代碼的人可能覺得有用炫狱。
(六)控制流 Control Flow
????????根據(jù)條件是否為真來決定是否執(zhí)行某些代碼藻懒,以及根據(jù)條件是否為真來重復(fù)運行一段代碼是大部分編程語言的基本組成部分。Rust 代碼中最常見的用來控制執(zhí)行流的結(jié)構(gòu)是?if?表達(dá)式和循環(huán)视译。
1束析、if?表達(dá)式
????????if?表達(dá)式允許根據(jù)條件執(zhí)行不同的代碼分支。你提供一個條件并表示 “如果條件滿足憎亚,運行這段代碼;如果條件不滿足弄慰,不運行這段代碼第美。
2、使用循環(huán)重復(fù)執(zhí)行
????????多次執(zhí)行同一段代碼是很常用的陆爽,Rust 為此提供了多種?循環(huán)(loops)什往。一個循環(huán)執(zhí)行循環(huán)體中的代碼直到結(jié)尾并緊接著回到開頭繼續(xù)執(zhí)行。為了實驗一下循環(huán)慌闭,讓我們新建一個叫做?loops?的項目别威。
Rust 有三種循環(huán):loop、while?和?for驴剔。
小結(jié):
????????通過以上的簡要介紹省古,我們了解了變量、標(biāo)量和復(fù)合數(shù)據(jù)類型丧失、函數(shù)豺妓、注釋、?if?表達(dá)式和循環(huán)布讹!如果想要對以上概念有更深入的了解琳拭,最好動手多敲敲代碼,從實踐和錯誤中學(xué)習(xí)描验,能更好地加深記憶白嘁,對Rust語法也會有更好的理解。?