Rust 學習#
基礎#
-
變數#
let a = 10; // a不可變 let mut a = 10 // a可變
Rust 在變數離開作用域後,就自動釋放內存,Rust 在結尾的 } 處自動調用 drop
-
基本類型#
2.1 數值類型#
語句:一個具體的操作,沒有返回值
表達式:表達式總要返回值
fn add_with_extra(x: i32, y: i32) -> i32 { let x = x + 1; // 語句 let y = y + 5; // 語句 x + y // 表達式 }
2.2 字符、布爾、單元類型#
String 類型:動態字符串類型,分配在堆上
let mut s = String::from("hello"); s.push_str(", world!") //在字符串追加字面值
Rust 中字符是 Unicode 類型,因此每個字符占據 4 個字節
字符串是 UTF-8 編碼,字符串中的字符所占的字節數是變化的 (1-4)
-
追加(Push)
let mut s = String::from("Hello ") s.push_str("rust") s.push('!')
push ():追加字符
push_str ():追加字符串
兩個方法都是在原有的字符串上追加,並不會返回新的字符串,所以該字符串必須是可變的,由 mut 關鍵字修飾
-
插入(Insert)
let mut s = String::from("Hello rust!") s.insert(5, ',') s.insert_str(6, " I like")
字符串插入操作要修改原來的字符串,所以該字符串必須是可變的,必須由 mut 關鍵字修飾
-
替換(Replace)
replace
let string_replace = String::from("I like rust") let new_string = string_replace.replace("rust", "Rust")
replacen
let s_replace = "I like rust learn rust" let ns_replacen = s_replace.replacen("rust", "Rust", 1)
字符串替換操作要返回一個新的字符串,而不是操作原來的字符串
replace_range:僅使用 String 類型
let mut s_replace_range = String::from("I like rust") s_replace_range.replace_range(7..8, "R")
該方法會直接操作原來的字符串,不會返回新的字符串,必須使用 mut 關鍵字修飾
-
刪除(Delete)
pop:刪除並返回最後一個字符
let mut s_pop = String::from("rust pop 中文!") let p1 = s_pop.pop()
該方法是直接操作原來的字符串,但是存在返回值,如果字符串是空,則返回 None
remove:刪除並返回字符串指定位置的字符
let mut s_remove = String::from("rust remove 中文") string_remove.remove(0)
該方法是直接操作原來的字符串,但是存在字符串
truncate:刪除字符串中從指定位置開始到結尾的全部字符
let mut s_truncate = String::from("測試truncate") s_truncate.truncate(3)
該方法是操作原來字符串,無返回值
clear:清空字符串
let mut s_clear = String::from("string clear") s_clear.clear()
該方法是直接操作原來的字符串,等價 s_clear.truncate (0)
-
連接(Concatenate)
使用 + 或 += 連接字符串,要求右邊的參數必須為字符串的切片引用 (Slice) 類型
+ 是返回一個新的字符串,所以變量聲明可以不需要 mut 關鍵字修飾
2.3 元組#
let x : (i32, f64, u8) = (500, 6.4, 1); let a = x.0; let b = x.1;
2.4 結構體#
- 初始化實例,每個字段都需要進行初始化
- 初始化字段順序不需要和定義時的一致
- 當函數參數和結構體字段同名時,可以直接使用縮略方式初始化
- user2 僅在 email 上和 user1 不同,因此只需要對 email 賦值,剩下通過..user1
fn build_user(email: String, username: String) -> User { User { email, username, active: true, sign_in_count: 1, } }
let user2 = User { email: String::from("[email protected]") ..user1 };
單元結構體:不關心該類型的內容,只關心它的行為
struct AlwaysEqual; let subject = AlwaysEqual; impl SomeTrait for AlwaysEqual {}
結構體輸出打印
- 手動實現 Display,Debug
- 使用派生類
#[derive(Debug)] struct Rectangle { width: u32, height: u32, } println!("rect1 is {:?}", rect1)
2.5 所有權和借用#
- Rust 中每一個值都被一個變量所擁有,改變量被稱為值的所有者
- 一個值同時只能被一個變量所擁有,或者說一個值只能擁有一個所有者
- 當所有者 (變量) 離開作用域範圍時,這個值將被丟棄,Rust 會自動調用 drop 函數並清理變量的堆內存
let s1 = String::from("hello"); let s2 = s1; println!("{}, world!", s1)
s1 被賦予 s2 後,Rust 認為 s1 不再有效,因此也無需在 s1 離開作用域後 drop 任何東西,這就是把所有權 s1 轉移給了 s2,s1 在被賦予 s2 後馬上失效了,Rust 禁止使用無效的引用
let x = 5; let y = x;
首先將 5 綁定到變量 x,接著拷貝 x 的值賦給 y,最終 x 和 y 都等於 5,整數是 Rust 基本數據類型,是固定大小的簡單值,因此這兩個值都是通過自動拷貝的方式來賦值的,都被存在棧中,無需堆上分配內存
2.6 引用和借用#
獲取變量的引用,稱之為借用
-
不可變引用
fn main() { let s1 = String::from("hello"); let len = calculate_len(&s1); println!("the len of '{}' is {}.", s1, len); } fn calculate_len(s: &String) -> usize { s.len() }
-
可變引用
fn main() { let mut s = String::from("hello"); change(&mut s); } fn change(some_string: &mut String) { some_string.push_str(", world"); }
- 不可變引用允許同時存在多個
- 可變引用同時只能存在一個
- 可變引用和不可變引用不能同時存在
-