搭建好了開發環境以後,就算是正式跳進Rust的坑了,今天我就要開始繼續向下挖了。 java
因爲咱們初來乍到 ,對Rust還不熟悉,因此我決定先走一遍常規套路。程序員
學習一門語言第一個要了解的固然就是變量啦。Rust使用關鍵字let
來定義變量。咱們寫一個簡單的demo編程
so easy!等等,這個小紅線是怎麼回事?編譯錯誤???彆着急,哪裏不對點哪裏。數組
IDEA告訴我,這個錯誤是bash
Cannot assign twice to immutable variable [E0384]
不可變的變量不能賦值兩次。我定義的變量是不可變的?這能叫變量?編程語言
官方文檔對此的解釋是,對於一個變量,你在一部分代碼中不但願它改變,而在另外一部分代碼中修改了它。那麼第一部分代碼的運行結果也許就不符合預期了。因此Rust的編譯器爲了杜絕這種狀況,也就是說Rust的變量默認是不可修改的。也就是說你只能對它賦值一次,以後它就是隻讀的了。有點像Java中的final變量。嗯…很嚴格。函數
但咱們編程中仍是須要變量的,怎麼辦?下面是跟着IDEA學習寫代碼環節。直接使用Alt + Enter,IDEA會在定義x時加上mut
關鍵字。oop
果真不會報錯了。感謝IDEA。接下來運行試試性能
The value of x is: 5 The value of x is: 6
打印結果符合咱們的預期。學習
mut
關鍵字在官方文檔也有解釋,定義變量時加上mut
,代表這個變量是一個可變變量。Rust之因此設計了可變變量,還有一個比較重要的緣由就是,對於比較複雜的數據類型,每次修改都要複製而且分配新的內存。這種性能損耗有時候是沒法接受的。所以能夠選擇使用可變變量來提升性能。
Rust自己也支持常量,可能大多數同窗和我有同樣的疑問,常量和不可變變量有什麼區別呢?
事實上它們仍是有區別的。最明顯的就是名字不同。(這是一句廢話)
主要的區別有如下幾種:
mut
關鍵字const
,而且須要指定數據類型。定義變量使用的是let
Rust是一門靜態編程語言,對於大多數靜態編程語言中,在同一範圍內,變量名是不容許重複的。可是Rust容許這樣定義。相似於這樣:
fn main() { let x = 5; let x = x + 1; let x = x + 2; println!("The value of x is: {}", x); }
這讓人看起來有些疑惑,做爲一個Java程序員,在我看來第二行就應該報編譯錯誤了。但咱們剛提到了Rust是容許這樣定義的。對於上述代碼來說,每次定義x都會覆蓋前一次定義的x。
對於Java來說,將一個int類型的變量轉換成String類型的變量可能須要這樣作:
int codeInt = 1; String codeStr = String.valueOf(codeInt);
咱們須要定義兩個變量來分別接收不一樣類型的變量,爲了變量名更有意義,可能要在變量名中加上變量類型。而在Rust中就不用考慮這個問題。
let s = "123"; let s: u32 = s.parse().expect("Not a number!");
這樣定義以後,再使用變量s時,它都是u32類型的變量了。
上面這個例子就是覆蓋變量和可變變量的區別:可變變量不能夠修改變量類型,覆蓋變量能夠作類型轉換。
可能有些同窗不太理解Rust爲何是靜態語言。這是由於在編譯階段,Rust編譯器必需要明確每一個變量的類型。編譯器一般會根據變量的值或者使用方法來爲變量指定一個數據類型。若是某個變量可能的數據類型有多個,那麼就須要開發者手動指定。
像上一節的例子中,第二次定義s若是不指定類型u32,編譯就會報錯。Rust支持的數據類型都有哪些呢?
和多數編程語言同樣,Rust支持的數據類型能夠分爲基本數據類型和複合數據類型兩大類。先說基本數據類型,基本數據類型分爲整數型、浮點型、布爾型和字符型。咱們逐個介紹一下。
Rust支持的整數類型分爲有符號整數和無符號整數
Length | Signed | Unsigned |
---|---|---|
8-bit | i8 | u8 |
16-bit | i16 | u16 |
32-bit | i32 | u32 |
64-bit | i64 | u64 |
128-bit | i128 | u128 |
arch | isize | usize |
若是沒有指定數據類型,Rust默認使用i32
,這個類型一般是性能最好的。
再順便聊一下整數的幾種表示。
Number literals | Example |
---|---|
Decimal | 98_222 |
Hex | 0xff |
Octal | 0o77 |
Binary | 0b1111_0000 |
Byte(u8) | b'A' |
十進制中_
通常被看成千分符。
Rust的浮點類型不像整型那麼多,它只支持兩種:f32和f64分別表示32位和64位浮點數,默認的浮點類型是f64。
布爾類型沒有什麼特別的,Rust支持隱式和顯式聲明兩種
let t = true; let f: bool = false;
須要注意的是字符類型char使用單引號,字符串使用雙引號。字符類型的值能夠是Unicode標準值。範圍是從U+0000到U+D7FF和U+E000到U+10FFFF。這意味着它能夠是中文韓文 emoji等等,而並不侷限於直覺上的「字符」。
聊完了基本數據類型,再來聊一聊複合類型,Rust包含兩種複合類型:Tuple和Array。
Tuple是一種能夠存儲不一樣類型的數字的集合。它的長度固定。聲明方法是:
let tup: (i32, f64, u8) = (500, 6.4, 1);
若是想要取得tuple中的某一個值,一般有兩種方法,一種是將tuple分別賦值給多個變量
fn main() { let tup = (500, 6.4, 1); let (x, y, z) = tup; println!("The value of y is: {}", y); }
另外一種方法是用直接用「.」來取值。
fn main() { let tup = (500, 6.4, 1); let x = tup.0; let y = tup.1; let z = tup.2; println!("x: {}, y: {}, z: {}", x, y, z); }
Array也是多個值的集合,但與Tuple不一樣的是,Array中的各個元素的數據類型必須相同。Array的長度也是固定的,這點上Rust的Array和其餘語言的有所不一樣。Array的定義方法是:
fn main() { let a = [1, 2, 3, 4, 5]; }
Rust的數組存儲在棧中,而不是堆。若是你不能在定義時肯定數組的長度,那麼須要使用vector類型,這個咱們在後面討論。Array還有一些其餘的定義方法。
let a: [i32; 5] = [1, 2, 3, 4, 5];
i32表示數組中元素的類型,5表示元素數量。
若是初始化時全部元素的值都相同,還能夠這樣定義:
let a = [3; 5];
這表示定義一個長度爲5的數組,每一個元素都是3。
函數在每一個編程語言中都是基本的概念,所以咱們不作過多贅述。Rust定義函數的方法是:
fn main() { let a = 1; let b = 2; let sum = add(a,b); println!("The value of sum is: {}", sum); } fn add(x: i32, y: i32) -> i32 { x + y }
Rust在定義函數時,須要指定參數的名稱和類型和返回值的類型。而返回值只能是表達式。做爲函數返回的表達式是不能以分號結尾的。
Rust的流程控制語句包括條件控制語句和循環語句。條件控制語句有if,循環語句包括loop、while和for。
Rust中if的條件必須是bool類型,它不像js中,會自動將變量轉換成bool類型。此外,if還能夠用於let語句中。例如:
let number = if condition { 5 } else { 6 };
這種方式須要注意的是,每一個表達式中返回的值必須是同一類型的。
loop循環中,若是沒有break或者是手動中止,那麼它會一直循環下去。寫法很簡單。
loop { println!("again!"); }
loop的用處是它能夠有返回值
let result = loop { counter += 1; if counter == 10 { break counter * 2; } };
while循環是當條件成立時進入循環。
while number != 0 { // do something }
當咱們須要遍歷數組時,可使用for循環。
for element in a.iter() { println!("the value is: {}", element); }
以上,是Rust的一些基本概念。和其餘的編程語言大同小異,記得一些特殊的地方就好,例如變量的不可變性。咱們還有一些數據類型沒有涉及,好比vector,String等,這些會在後面詳細講解。
至此,我已經又向下挖了一層了。不知道你入坑了沒有?已經入坑的同窗還請麻煩幫忙往外刨(分)土(享)。