Rust入坑指南:常規套路


搭建好了開發環境之后,就算是正式跳進Rust的坑了,今天我就要開始繼續向下挖了。

由於我們初來乍到 ,對Rust還不熟悉,所以我決定先走一遍常規套路。

變不變的變量

學習一門語言第一個要了解的當然就是變量啦。Rust使用關鍵字let來定義變量。我們寫一個簡單的demo

demo1

so easy!等等,這個小紅線是怎么回事?編譯錯誤???別着急,哪里不對點哪里。

IDEA告訴我,這個錯誤是

Cannot assign twice to immutable variable [E0384]

不可變的變量不能賦值兩次。我定義的變量是不可變的?這能叫變量?

官方文檔對此的解釋是,對於一個變量,你在一部分代碼中不希望它改變,而在另一部分代碼中修改了它。那么第一部分代碼的運行結果也許就不符合預期了。所以Rust的編譯器為了杜絕這種情況,也就是說Rust的變量默認是不可修改的。也就是說你只能對它賦值一次,之后它就是只讀的了。有點像Java中的final變量。嗯…很嚴格。

但我們編程中還是需要變量的,怎么辦?下面是跟着IDEA學習寫代碼環節。直接使用Alt + Enter,IDEA會在定義x時加上mut關鍵字。

demo2

果然不會報錯了。感謝IDEA。接下來運行試試

The value of x is: 5
The value of x is: 6

打印結果符合我們的預期。

mut關鍵字在官方文檔也有解釋,定義變量時加上mut,表明這個變量是一個可變變量。Rust之所以設計了可變變量,還有一個比較重要的原因就是,對於比較復雜的數據類型,每次修改都要復制並且分配新的內存。這種性能損耗有時候是無法接受的。因此可以選擇使用可變變量來提高性能。

變量和常量

Rust本身也支持常量,可能大多數同學和我有一樣的疑問,常量和不可變變量有什么區別呢?

事實上它們還是有區別的。最明顯的就是名字不一樣。(這是一句廢話)

主要的區別有以下幾種:

  1. 定義常量時不能使用mut關鍵字
  2. 常量定義使用的關鍵字是const,並且需要指定數據類型。定義變量使用的是let
  3. 常量可以在任何范圍內定義,並且可以在多個代碼塊中使用
  4. 給常量賦值時,不能使用函數的返回值或者是計算式。只能使用一個「常量」

變量的覆蓋

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類型

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類型

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。

if

Rust中if的條件必須是bool類型,它不像js中,會自動將變量轉換成bool類型。此外,if還可以用於let語句中。例如:

let number = if condition {
  5
} else { 
  6
};

這種方式需要注意的是,每個表達式中返回的值必須是同一類型的。

loop

loop循環中,如果沒有break或者是手動停止,那么它會一直循環下去。寫法很簡單。

loop {
  println!("again!");
}

loop的用處是它可以有返回值

let result = loop {
  counter += 1;

  if counter == 10 {
    break counter * 2;
  }
};

while

while循環是當條件成立時進入循環。

while number != 0 {
  // do something
}

for

當我們需要遍歷數組時,可以使用for循環。

for element in a.iter() {
  println!("the value is: {}", element);
}

總結

以上,是Rust的一些基本概念。和其他的編程語言大同小異,記得一些特殊的地方就好,例如變量的不可變性。我們還有一些數據類型沒有涉及,比如vector,String等,這些會在后面詳細講解。

至此,我已經又向下挖了一層了。不知道你入坑了沒有?已經入坑的同學還請麻煩幫忙往外刨(分)土(享)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM