網(wǎng)站建設方案 安全優(yōu)化營商環(huán)境心得體會2023
rust一些通用編程的概念
官網(wǎng)文檔數(shù)據(jù)類型 - Rust 程序設計語言 中文版 (rustwiki.org)
變量,數(shù)據(jù)類型,條件判斷,循環(huán)
-
變量
rust中變量的可變性是值得注意的
例如:
fn main(){let number = 1;number = 2;println!("the number is {}",number); }
let關鍵字定義的變量默認無法改變,上述的方式會導致運行報錯
使用cargo run運行時得到以下結果
PS D:\rust_project\demo2> cargo runCompiling demo2 v0.1.0 (D:\rust_project\demo2) warning: value assigned to `number` is never read--> src/main.rs:2:9| 2 | let number = 1;| ^^^^^^|= help: maybe it is overwritten before being read?= note: `#[warn(unused_assignments)]` on by defaulterror[E0384]: cannot assign twice to immutable variable `number`--> src/main.rs:3:5| 2 | let number = 1;| ------ first assignment to `number` 3 | number = 2;| ^^^^^^^^^^ cannot assign twice to immutable variable| help: consider making this binding mutable| 2 | let mut number = 1;| +++For more information about this error, try `rustc --explain E0384`. warning: `demo2` (bin "demo2") generated 1 warning error: could not compile `demo2` (bin "demo2") due to 1 previous error; 1 warning emitted
因為這里let直接定義的屬于不可變變量,如果你需要定義一個可變變量需要使用mut關鍵字
fn main(){let mut number = 1;number = 2;println!("the number is {}",number); }
結果就可以正常運行,不過會有相對應的warnning
warning: value assigned to `number` is never read--> src/main.rs:2:13| 2 | let mut number = 1;| ^^^^^^|= help: maybe it is overwritten before being read?= note: `#[warn(unused_assignments)]` on by defaultwarning: `demo2` (bin "demo2") generated 1 warningFinished `dev` profile [unoptimized + debuginfo] target(s) in 0.47sRunning `target\debug\demo2.exe` the number is 2
再引入一個概念
常量
常量和不可變變量類似,用于綁定到一個常量名且不允許更改的值,但是常量和變量之間存在一定差異,常量不允許使用mut關鍵字
且自始至終無法改變,使用const關鍵字定義常量,同時必須標注數(shù)據(jù)類型,常量可以在任意作用域中聲明,包括全局作用域,且無法為函數(shù)調(diào)用結果或只能在運算時得到的值
fn main(){const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;println!("the time is {}",THREE_HOURS_IN_SECONDS);}
D:\rust_project\demo2>cargo runCompiling demo2 v0.1.0 (D:\rust_project\demo2)Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.35sRunning `target\debug\demo2.exe` the time is 10800
遮掩
可以通過聲明相同的變量名稱來遮蓋前面一個變量
fn main() {let x = 5;let x = x + 1;{let x = x * 2;println!("The value of x in the inner scope is: {}", x);}println!("The value of x is: {}", x); }
The value of x in the inner scope is: 12 The value of x is: 6
遮掩與mut區(qū)別在于
- 遮掩需要重新使用let定義新變量來遮蓋達到修改原先變量的值,而mut不需要
- 遮掩是創(chuàng)建一個新變量所以可以改變原先變量的數(shù)據(jù)類型,但是mut始終一個變量類型
fn main() {let spaces = " ";let spaces = spaces.len(); }
這其中第一個spaces為字符串類型,第二個為數(shù)字類型
fn main() {let mut spaces = " ";spaces = spaces.len(); }
而這樣編譯器則會報錯
Compiling demo2 v0.1.0 (D:\rust_project\demo2) error: format argument must be a string literal--> src/main.rs:4:14| 4 | println!(spaces)| ^^^^^^| help: you might be missing a string literal to format with| 4 | println!("{}", spaces)| +++++error: could not compile `demo2` (bin "demo2") due to 1 previous error
-
數(shù)據(jù)類型
rust是一種靜態(tài)類型語言,因此它在編譯期必須知道所有變量的類型,rust每一個值都有確切的數(shù)據(jù)類型
一般可以在變量名稱后面使用英文冒號加數(shù)據(jù)類型的方式進行標注
eg.
let guess: u32 = "42".parse().expect("Not a number!");
: u32表示guess是一個無符號的32位整型數(shù)據(jù)
同時這段代碼必須加上對應的:u32數(shù)據(jù)標注,因為等式的右邊采用parse()方法將String類型轉為數(shù)值類型時,必須顯性的聲明變量的數(shù)據(jù)類型
否則報錯
error[E0282]: type annotations needed--> src/main.rs:2:9| 2 | let guess = "42".parse().expect("Not a number!");| ^^^^^ consider giving `guess` a typeFor more information about this error, try `rustc --explain E0282`. error: could not compile `no_type_annotations` due to previous error
標量類型
標量類型表示單個值。Rust有4個基本的標量類型:整型、浮點型、布爾型和字符
-
整數(shù)類型
長度 有符號類型 無符號類型 8位 i8 u8 16 位 i16 u16 32 位 i32 u32 64 位 i64 u64 128 位 i128 u128 arch isize usize 有無符號表示是否取負數(shù),每個有符號類型規(guī)定的數(shù)字范圍是 -(2n - 1) ~ 2n - 1 - 1,其中
n
是該定義形式的位長度。所以i8
可存儲數(shù)字范圍是 -(27) ~ 27 - 1,即 -128 ~ 127。無符號類型可以存儲的數(shù)字范圍是 0 ~ 2n - 1,所以u8
能夠存儲的數(shù)字為 0 ~ 28 - 1,即 0 ~ 255。此外,
isize
和usize
類型取決于程序運行的計算機體系結構,在表中表示為“arch”:若使用 64 位架構系統(tǒng)則為 64 位,若使用 32 位架構系統(tǒng)則為 32 位。可能屬于多種數(shù)字類型的數(shù)字字面量允許使用類型后綴來指定類型,例如
57u8
。數(shù)字字面量還可以使用_
作為可視分隔符以方便讀數(shù),如1_000
,此值和1000
相同。數(shù)字字面量 示例 十進制 98_222 十六進制 0xff 八進制 0o77 二進制 0b1111_0000 字節(jié) (僅限于 u8
)b’A’ 同時如果不確定整數(shù)類型,rust通常會默認i32
-
浮點數(shù)
帶有小數(shù)的數(shù)字
浮點數(shù)按照 IEEE-754 標準表示。
f32
類型是單精度浮點型,f64
為雙精度浮點型。Rust 的所有數(shù)字類型都支持基本數(shù)學運算:加法、減法、乘法、除法和取模運算。整數(shù)除法會向下取整。下面代碼演示了各使用一條
let
語句來說明相應數(shù)字運算的用法:fn main() {// additionlet sum = 5 + 10;// subtractionlet difference = 95.5 - 4.3;// multiplicationlet product = 4 * 30;// divisionlet quotient = 56.7 / 32.2;let floored = 2 / 3; // Results in 0// remainderlet remainder = 43 % 5; }
-
布爾類型
表示是否,和大多數(shù)編程語言一樣
fn main() {let t = true;let f: bool = false; // with explicit type annotation }
-
字符類型
Rust 的
char
(字符)類型是該語言最基本的字母類型,且為4個字節(jié)支持Unicode編碼下面是一些聲明char
值的例子:fn main() {let c = 'z';let z = '?';let heart_eyed_cat = '😻'; }
-
復合類型
-
元組
和python中的元組概念類似
可以將多種類型的值組合到一個復合類型中
fn main() {let tup: (i32, f64, u8) = (500, 6.4, 1); }
同時可以使用模式解構的方式獲取元組中的某個值
fn main() {let tup: (i32,u32,f64,bool) = (-1,1121,3.1415926,true);let (x,y,z,w) = tup;println!("The value of x is: {}",x); }
D:\rust_project\demo2>cargo runCompiling demo2 v0.1.0 (D:\rust_project\demo2) warning: unused variable: `y`--> src/main.rs:3:12| 3 | let (x,y,z,w) = tup;| ^ help: if this is intentional, prefix it with an underscore: `_y`|= note: `#[warn(unused_variables)]` on by defaultwarning: unused variable: `z`--> src/main.rs:3:14| 3 | let (x,y,z,w) = tup;| ^ help: if this is intentional, prefix it with an underscore: `_z`warning: unused variable: `w`--> src/main.rs:3:16| 3 | let (x,y,z,w) = tup;| ^ help: if this is intentional, prefix it with an underscore: `_w`warning: `demo2` (bin "demo2") generated 3 warningsFinished `dev` profile [unoptimized + debuginfo] target(s) in 0.35sRunning `target\debug\demo2.exe` The value of x is: -1
也可以利用.運算符來獲取元組中的某個值,同時索引從0開始
warning: unused variable: `x`--> src/main.rs:3:10| 3 | let (x,y,z,w) = tup;| ^ help: if this is intentional, prefix it with an underscore: `_x`|= note: `#[warn(unused_variables)]` on by defaultwarning: unused variable: `y`--> src/main.rs:3:12| 3 | let (x,y,z,w) = tup;| ^ help: if this is intentional, prefix it with an underscore: `_y`warning: unused variable: `z`--> src/main.rs:3:14| 3 | let (x,y,z,w) = tup;| ^ help: if this is intentional, prefix it with an underscore: `_z`warning: unused variable: `w`--> src/main.rs:3:16| 3 | let (x,y,z,w) = tup;| ^ help: if this is intentional, prefix it with an underscore: `_w`warning: `demo2` (bin "demo2") generated 4 warningsFinished `dev` profile [unoptimized + debuginfo] target(s) in 0.35sRunning `target\debug\demo2.exe` The value of x is: -1
-
數(shù)組類型
寫法上等同于python中的列表,但是概念等同于c語言
fn main() {let array = [1,2,3];println!("{}", array[0]) }
D:\rust_project\demo2>cargo runCompiling demo2 v0.1.0 (D:\rust_project\demo2)Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.35sRunning `target\debug\demo2.exe` 1
但是數(shù)組長度不可變,數(shù)組中的數(shù)據(jù)類型必須一致
顯示寫法
fn main() { let a: [i32; 5] = [1, 2, 3, 4, 5]; }
這里,
i32
是每個元素的類型。分號之后,數(shù)字5
表明該數(shù)組包含 5 個元素。如果要為每個元素創(chuàng)建包含相同值的數(shù)組,可以指定初始值,后跟分號,然后在方括號中指定數(shù)組的長度,如下所示:
fn main() { let a = [3; 5]; }
-
-
-
函數(shù)
其實很類似與python的顯示函數(shù)聲明
通過關鍵字fn自定義函數(shù)
main函數(shù)便是rust程序的啟動入口
fn main() {println!("Hello, world!");another_function(); }fn another_function() {println!("Another function."); }
$ cargo runCompiling functions v0.1.0 (file:///projects/functions)Finished dev [unoptimized + debuginfo] target(s) in 0.28sRunning `target/debug/functions` Hello, world! Another function.
參數(shù)
函數(shù)也可以被定義為擁有參數(shù)(parameter),參數(shù)是特殊變量,是函數(shù)簽名的一部分。當函數(shù)擁有參數(shù)(形參)時,可以為這些參數(shù)提供具體的值(實參)。技術上講,這些具體值被稱為實參(argument),但是在日常交流中,人們傾向于不區(qū)分使用 parameter 和 argument 來表示函數(shù)定義中的變量或調(diào)用函數(shù)時傳入的具體值。
在函數(shù)簽名中,必須聲明每個參數(shù)的類型。這是一個 Rust 設計中經(jīng)過慎重考慮的決定:要求在函數(shù)定義中提供類型標注,意味著編譯器幾乎從不需要你在代碼的其他地方注明類型來指出你的意圖。
當一個函數(shù)有多個參數(shù)時,使用逗號分隔,像這樣:
fn main() {print_labeled_measurement(5, 'h'); }fn print_labeled_measurement(value: i32, unit_label: char) {println!("The measurement is: {}{}", value, unit_label); }
這個例子創(chuàng)建了一個有兩個參數(shù)的名為
print_labeled_measurement
的函數(shù)。第一個參數(shù)名為value
, 類型是i32
。第二個參數(shù)是unit_label
,類型是char
。接著該函數(shù)打印包含value
和unit_label
的文本。語句和表達式
函數(shù)體由一系列語句組成,也可選擇以表達式結尾。目前為止,我們介紹的函數(shù)還沒有包含結尾表達式,不過你已經(jīng)看到了表達式作為語句的一部分。因為 Rust 是一門基于表達式(expression-based)的語言,所以這是一個需要理解的重要區(qū)別。其他語言沒有這樣的區(qū)別,所以讓我們看看語句和表達式分別是什么,以及它們的區(qū)別如何影響函數(shù)體。
語句(statement)是執(zhí)行一些操作但不返回值的指令。表達式(expression)計算并產(chǎn)生一個值。讓我們看一些例子:
實際上,我們已經(jīng)使用過語句和表達式。使用
let
關鍵字創(chuàng)建變量并綁定一個值是一個語句。在示例中,let y = 6;
是一個語句。fn main() {let y = 6; }
函數(shù)定義也是語句,上面整個例子本身就是一個語句。
語句不返回值。因此,不能把
let
語句賦值給另一個變量,就像下面的代碼嘗試做的那樣,會產(chǎn)生一個錯誤:fn main() {let x = (let y = 6); }
$ cargo runCompiling functions v0.1.0 (file:///projects/functions) error: expected expression, found statement (`let`)--> src/main.rs:2:14| 2 | let x = (let y = 6);| ^^^^^^^^^|= note: variable declaration using `let` is a statementerror[E0658]: `let` expressions in this position are experimental--> src/main.rs:2:14| 2 | let x = (let y = 6);| ^^^^^^^^^|= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information= help: you can write `matches!(<expr>, <pattern>)` instead of `let <pattern> = <expr>`warning: unnecessary parentheses around assigned value--> src/main.rs:2:13| 2 | let x = (let y = 6);| ^ ^|= note: `#[warn(unused_parens)]` on by default help: remove these parentheses| 2 - let x = (let y = 6); 2 + let x = let y = 6;| For more information about this error, try `rustc --explain E0658`. warning: `functions` (bin "functions") generated 1 warning error: could not compile `functions` due to 2 previous errors; 1 warning emitted
表達式會計算出一個值,考慮一個數(shù)學運算,比如
5 + 6
,這是一個表達式并計算出值11
。表達式可以是語句的一部分語句
let y = 6;
中的6
是一個表達式,它計算出的值是6
。函數(shù)調(diào)用是一個表達式。宏調(diào)用是一個表達式。我們用來創(chuàng)建新作用域的大括號(代碼塊){}
也是一個表達式,例如fn main() {let y = {let x = 3;x + 1};println!("The value of y is: {}", y); }
中這個就是表達式
{let x = 3;x + 1 }
是一個代碼塊,在這個例子中計算結果是
4
。這個值作為let
語句的一部分被綁定到y
上。注意,x + 1
行的末尾沒有分號,這與你目前見過的大部分代碼行不同。表達式的結尾沒有分號。如果在表達式的末尾加上分號,那么它就轉換為語句,而語句不會返回值。在接下來探討函數(shù)返回值和表達式時帶有返回值的函數(shù)
函數(shù)可以向調(diào)用它的代碼返回值。我們并不對返回值命名,但要在箭頭(
->
)后聲明它的類型。在 Rust 中,函數(shù)的返回值等同于函數(shù)體最后一個表達式的值。使用return
關鍵字和指定值,可以從函數(shù)中提前返回;但大部分函數(shù)隱式返回最后一個表達式。這是一個有返回值函數(shù)的例子:fn five() -> i32 {5 }fn main() {let x = five();println!("The value of x is: {}", x); }
在
five
函數(shù)中沒有函數(shù)調(diào)用、宏,甚至沒有let
語句——只有數(shù)字5
本身。這在 Rust 中是一個完全有效的函數(shù)。注意,函數(shù)返回值的類型也被指定好,即-> i32
。嘗試運行代碼;輸出應如下所示:$ cargo runCompiling functions v0.1.0 (file:///projects/functions)Finished dev [unoptimized + debuginfo] target(s) in 0.30sRunning `target/debug/functions` The value of x is: 5
five
函數(shù)的返回值是5
,所以返回值類型是i32
。讓我們仔細檢查一下這段代碼。有兩個重要的部分:首先,let x = five();
這一行表明我們使用函數(shù)的返回值初始化一個變量。因為five
函數(shù)返回5
,這一行與如下代碼相同:#![allow(unused)] fn main() { let x = 5; }
其次,
five
函數(shù)沒有參數(shù)并定義了返回值類型,不過函數(shù)體只有單單一個5
也沒有分號,因為這是一個表達式,正是我們想要返回的值。讓我們看看另一個例子:
fn main() {let x = plus_one(5);println!("The value of x is: {}", x); }fn plus_one(x: i32) -> i32 {x + 1 }
運行代碼會打印出
The value of x is: 6
。但如果在包含x + 1
的行尾加上一個分號,把它從表達式變成語句,我們將得到一個錯誤。fn main() {let x = plus_one(5);println!("The value of x is: {}", x); }fn plus_one(x: i32) -> i32 {x + 1; }
$ cargo runCompiling functions v0.1.0 (file:///projects/functions) error[E0308]: mismatched types--> src/main.rs:7:24| 7 | fn plus_one(x: i32) -> i32 {| -------- ^^^ expected `i32`, found `()`| || implicitly returns `()` as its body has no tail or `return` expression 8 | x + 1;| - help: consider removing this semicolonFor more information about this error, try `rustc --explain E0308`. error: could not compile `functions` due to previous error
主要的錯誤信息 “mismatched types”(類型不匹配)揭示了這段代碼的核心問題。函數(shù)
plus_one
的定義說明它要返回一個i32
類型的值,不過語句并不會返回值,此值由單元類型()
表示,表示不返回值。因為不返回值與函數(shù)定義相矛盾,從而出現(xiàn)一個錯誤。在輸出中,Rust 提供了一條信息,可能有助于糾正這個錯誤:它建議刪除分號,這將修復錯誤。不過使用return也可以正常返回
fn main() {let res = add(1,2);println!("{}", res);} fn add(value_first: i32, value_second: i32)->i32{return value_first + value_second; }
D:\rust_project\demo2>cargo runCompiling demo2 v0.1.0 (D:\rust_project\demo2)Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.34sRunning `target\debug\demo2.exe` 3
-
注釋
和c語言一樣,//和/**/
還有一種文檔注釋后期說明
-
控制流
根據(jù)條件是否為真來決定是否執(zhí)行某些代碼,或根據(jù)條件是否為真來重復運行一段代碼,是大部分編程語言的基本組成部分。Rust 代碼中最常見的用來控制執(zhí)行流的結構是
if
表達式和循環(huán)。if
表達式if
表達式允許根據(jù)條件執(zhí)行不同的代碼分支。你提供一個條件并表示 “如果條件滿足,運行這段代碼;如果條件不滿足,不運行這段代碼。fn main() {let number = 3;if number < 5 {println!("condition was true");} else {println!("condition was false");} }
$ cargo runCompiling branches v0.1.0 (file:///projects/branches)Finished dev [unoptimized + debuginfo] target(s) in 0.31sRunning `target/debug/branches` condition was true
值得注意的是代碼中的條件必須是
bool
值。如果條件不是bool
值,我們將得到一個錯誤。例如fn main() {let number = 3;if number {println!("number was three");} }
$ cargo runCompiling branches v0.1.0 (file:///projects/branches) error[E0308]: mismatched types--> src/main.rs:4:8| 4 | if number {| ^^^^^^ expected `bool`, found integerFor more information about this error, try `rustc --explain E0308`. error: could not compile `branches` due to previous error
必須自始至終顯式地使用布爾值作為
if
的條件使用
else if
處理多重條件可以將
if
和else
組成的else if
表達式來實現(xiàn)多重條件。例如:fn main() {let number = 6;if number % 4 == 0 {println!("number is divisible by 4");} else if number % 3 == 0 {println!("number is divisible by 3");} else if number % 2 == 0 {println!("number is divisible by 2");} else {println!("number is not divisible by 4, 3, or 2");} }
在
let
語句中使用if
因為
if
是一個表達式,我們可以在let
語句的右側使用它來將結果賦值給一個變量,例如:fn main() {let condition = true;let number = if condition { 5 } else { 6 };println!("The value of number is: {}", number); }
其實就是三元運算符
但是記住,代碼塊的值是其最后一個表達式的值,而數(shù)字本身就是一個表達式。在這個例子中,整個
if
表達式的值取決于哪個代碼塊被執(zhí)行。這意味著if
的每個分支的可能的返回值都必須是相同類型;在示例中,if
分支和else
分支的結果都是i32
整型。如果它們的類型不匹配,如下面這個例子,則會產(chǎn)生一個錯誤:fn main() {let condition = true;let number = if condition { 5 } else { "six" };println!("The value of number is: {}", number); }
$ cargo runCompiling branches v0.1.0 (file:///projects/branches) error[E0308]: `if` and `else` have incompatible types--> src/main.rs:4:44| 4 | let number = if condition { 5 } else { "six" };| - ^^^^^ expected integer, found `&str`| || expected because of thisFor more information about this error, try `rustc --explain E0308`. error: could not compile `branches` due to previous error
循環(huán)控制流
在 Rust 中,循環(huán)控制流主要包括三種類型的循環(huán):
loop
、while
和for
。它們的區(qū)別在于使用場景、語法以及控制流的特點。以下是對這三種循環(huán)的詳細論述:1.
loop
循環(huán)loop
是 Rust 中的無限循環(huán)語句。它會無限執(zhí)行其內(nèi)部的代碼塊,直到明確使用break
退出循環(huán)。適用于需要無限循環(huán)的場景,比如服務的事件循環(huán)。示例:
let mut count = 0; loop {count += 1;if count == 10 {break;}println!("Count: {}", count); }
-
特點:
- 無條件循環(huán),需要手動使用
break
來退出。 - 可以通過
continue
跳過當前循環(huán)并進入下一次循環(huán)。 - 適用于無法確定循環(huán)次數(shù)或者需要手動控制的循環(huán)場景。
- 無條件循環(huán),需要手動使用
-
返回值:
loop
循環(huán)可以返回值,通常與break
結合使用。
let result = loop {count += 1;if count == 10 {break count * 2; // 返回值為 20} };
2.
while
循環(huán)while
是基于條件判斷的循環(huán),在條件為true
時重復執(zhí)行代碼塊,條件為false
時退出循環(huán)。示例:
let mut number = 3; while number != 0 {println!("{}!", number);number -= 1; } println!("Liftoff!");
-
特點:
- 依賴布爾條件的判斷,當條件為
false
時自動結束。 - 適用于條件驅(qū)動的循環(huán)場景。
- 依賴布爾條件的判斷,當條件為
-
優(yōu)點:
- 比
loop
更靈活和安全,因為它不需要顯式地使用break
。
- 比
3.
for
循環(huán)for
循環(huán)用于遍歷集合(如數(shù)組、迭代器、范圍等)。它是 Rust 中最常用的循環(huán)形式。示例:
let a = [10, 20, 30, 40, 50]; for element in a.iter() {println!("The value is: {}", element); }
-
特點:
- 適合遍歷固定范圍或者集合類型(如數(shù)組、切片等)。
- 語法簡潔,自動處理索引范圍,不容易出現(xiàn)越界錯誤。
-
使用范圍語法:
for number in 1..4 {println!("{}!", number); // 輸出 1, 2, 3 }
-
迭代器結合:
for
循環(huán)與迭代器結合非常方便,可以利用 Rust 提供的強大迭代器機制來簡化循環(huán)操作。
小結:
loop
:無限循環(huán),適用于需要手動控制退出的場景。while
:條件驅(qū)動的循環(huán),適合在滿足某個條件時執(zhí)行的操作。for
:集合或范圍遍歷,最常用的循環(huán)形式,安全且簡潔。
-