程式語言:Rust
官網
Rust Playground(線上撰寫)
簡介:Rust 的特色介紹
因此任何自動的拷貝動作都可以被視為是對執行效能影響很小的,但可手動 clone
若只在堆疊(Stack)上的資料,會自動拷貝,因擁有 Copy Trait,如下型別
官網
Rust Playground(線上撰寫)
簡介:Rust 的特色介紹
學習資源
變數可被遮蔽
線上測試範例
線上測試範例
- fn main() {
- let x = 5;
- println!("x 的數值為:{}", x);
- let x = "five";
- println!("x 的數值為:{}", x);
- }
變數宣告
使用前必須有值
線上測試範例
線上測試範例
- fn main() {
- // // type annotations needed
- let x;
- println!("x 的數值為:{}", x);
- // borrow of possibly-uninitialized variable: `x`
- let x;
- println!("x 的數值為:{}", x);
- x=2;
- // OK
- let x;
- x=2;
- println!("x 的數值為:{}", x);
- }
宣告時,需指定變數是否可變
線上測試範例
線上測試範例
- fn main() {
- // 不可變
- let x = 5;
- println!("x 的數值為:{}", x);
- // cannot assign twice to immutable variable `x`
- x = 6;
- println!("x 的數值為:{}", x);
- // 可變
- let mut x = 5;
- println!("x 的數值為:{}", x);
- x = 6;
- println!("x 的數值為:{}", x);
- }
- Rust 中每個數值都會有一個變數作為它的擁有者(owner)。
- 同時間只能有一個擁有者。
- 當擁有者離開作用域時,數值就會被丟棄。
因此任何自動的拷貝動作都可以被視為是對執行效能影響很小的,但可手動 clone
若只在堆疊(Stack)上的資料,會自動拷貝,因擁有 Copy Trait,如下型別
- 所有整數型別像是 u32。
- 布林型別 bool,它只有數值 true 與 false。
- 所有浮點數型別像是 f64。
- 字元型別 char。
- 元組,不過包含的型別也都要有 Copy 才行。比如 (i32, i32) 就有 Copy,但 (i32, String) 則無。
- fn main() {
- {
- // s 在此處無效,因為它還沒宣告
- let s = "hello"; // s 在此開始視為有效
- println!("{}", s); // 使用 s
- } // 此作用域結束, s 不再有效
- // cannot find value `s` in this scope
- println!("{}", s); // 會出錯
- //=========================================================
- let s1 = String::from("hello");
- let s2 = s1;
- // borrow of moved value: `s1`
- println!("{}", s1); // 會出錯
- //=========================================================
- let x = 5;
- let y = x;
- println!("{}", x); // 不會出錯,因為 Copy Trait
- //=========================================================
- let s1 = String::from("hello");
- let s2 = s1.clone();
- println!("s1 = {}, s2 = {}", s1, s2); // 不會出錯,因重新 clone 一份給 s2
- }
基本用法,可用引用閃過所有權
線上測試範例
線上測試範例
限制條件
- fn main() {
- let s1 = String::from("hello");
- let s2 = &s1;
- println!("{} {}", s1, s2); // 不會出錯,因 s2 為引用
- //cannot borrow `*s2` as mutable, as it is behind a `&` reference
- // s2.push_str(", world"); // 因 s2 為不可變引用,故會出錯
- // println!("{}", s2);
- let mut s3 = String::from("hello");
- let s4 = &mut s3;
- s4.push_str(", world");
- println!("{}", s4);
- // cannot borrow `s1` as mutable, as it is not declared as mutable
- let s5 = &mut s1;
- s5.push_str(", world");
- println!("{}", s5);
- }
- 在任何時候,我們要嘛只能有一個可變引用,要嘛可以有任意數量的不可變引用。
- 引用必須永遠有效。
- 同時有兩個以上的指標存取同個資料。
- 至少有一個指標在寫入資料。
- 沒有針對資料的同步存取機制。
- fn main() {
- let mut s = String::from("hello");
- let r1 = &mut s;
- // cannot borrow `s` as mutable more than once at a time
- let r2 = &mut s;
- println!("{}, {}", r1, r2);
- //===================================================
- let mut s = String::from("hello");
- {
- let r1 = &mut s;
- } // r1 離開作用域,所以建立新的引用也不會有問題
- let r2 = &mut s;
- //===================================================
- let mut s = String::from("hello");
- let r1 = &s; // 沒問題
- let r2 = &s; // 沒問題
- // cannot borrow `s` as mutable because it is also borrowed as immutable
- let r3 = &mut s; // 很有問題!
- println!("{}, {}, and {}", r1, r2, r3);
- //===================================================
- let mut s = String::from("hello");
- let r1 = &s; // 沒問題
- let r2 = &s; // 沒問題
- println!("{} and {}", r1, r2);
- // r1 和 r2 從此不再使用
- let r3 = &mut s; // 沒問題
- println!("{}", r3);
- //===================================================
- {
- let mut s = String::from("hello");
- } // s 離開作用域,已被 drop
- // cannot find value `s` in this scope
- let r1 = &mut s; // 很有問題!
- }
線上測試範例
- #![allow(unused)]
- fn main() {
- use std::fs::File;
- use std::io;
- use std::io::Read;
- fn read_username_from_file() -> Result<String, io::Error> {
- let f = File::open("hello.txt");
- let mut f = match f {
- Ok(file) => file,
- Err(e) => return Err(e),
- };
- let mut s = String::new();
- match f.read_to_string(&mut s) {
- Ok(_) => Ok(s),
- Err(e) => Err(e),
- }
- }
- // 利用 ? 可達到同上的效果 ===========================
- fn read_username_from_file() -> Result<String, io::Error> {
- let mut f = File::open("hello.txt")?;
- let mut s = String::new();
- f.read_to_string(&mut s)?;
- Ok(s)
- }
- }
可利用特徵界限,來限定型別
- // 以下兩者等同
- fn trait_fn<T: Copy + Debug>(a: T) -> T {}
- fn trait_where<T>(a: T) -> T
- where
- T: Copy + Debug,
- {
- }
- // 以下兩者等同
- fn trait_iml(a: impl Copy) -> impl Copy {}
- fn trait_iml<T: Copy>(a: T) -> impl Copy {}
- // impl Trait 語法糖,只在輸入參數,回傳型別並不相同
- // 故以下兩者不等同
- fn trait_iml(a: impl Copy) -> impl Copy {}
- fn trait_iml<T: Copy>(a: T) -> T {}
生命週期詮釋不會改變引用能存活多久。
就像當函式簽名指定了一個泛型型別參數時,函式便能夠接受任意型別一樣。
函式可以指定一個泛型生命週期參數,這樣函式就能接受任何生命週期。
生命週期詮釋描述了數個引用的生命週期之間互相的關係,而不會影響其生命週期。
當引用沒有顯式詮釋生命週期時,編譯器會用三項規則來推導它們。
就像當函式簽名指定了一個泛型型別參數時,函式便能夠接受任意型別一樣。
函式可以指定一個泛型生命週期參數,這樣函式就能接受任何生命週期。
生命週期詮釋描述了數個引用的生命週期之間互相的關係,而不會影響其生命週期。
當引用沒有顯式詮釋生命週期時,編譯器會用三項規則來推導它們。
- 第一個規則是每個引用都會有自己的生命週期參數。換句話說,一個函式只有一個參數的話,就只會有一個生命週期:
fn foo<'a>(x: &'a i32);
一個函式有兩個參數的話,就會有分別兩個生命週期參數:fn foo<'a, 'b>(x: &'a i32, y: &'b i32)
,以此類推。 - 第二個規則是如果剛好只有一個輸入生命週期參數,該參數就會賦值給所有輸出生命週期參數:
fn foo<'a>(x: &'a i32) -> &'a i32。
- 第三個規則是如果有多個輸入生命週期參數,但其中一個是 &self 或 &mut self,由於這是方法,self 的生命週期會賦值給所有輸出生命週期參數。此規則讓方法更容易讀寫,因為不用寫更多符號出來。
- fn main() {
- let string1 = String::from("abcd");
- let string2 = "xyz";
- let result = longest(string1.as_str(), string2);
- println!("最長的字串為 {}", result);
- }
- fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
- if x.len() > y.len() {
- x
- } else {
- y
- }
- }
let 即是一種 模式配對
線上測試範例
- struct Point {
- x: i32,
- y: i32,
- }
- fn main() {
- let p = Point { x: 0, y: 7 };
- let Point { x: a, y: b } = p;
- assert_eq!(0, a);
- assert_eq!(7, b);
- }
- enum Color {
- Rgb(i32, i32, i32),
- Hsv(i32, i32, i32),
- }
- enum Message {
- Quit,
- Move { x: i32, y: i32 },
- Write(String),
- ChangeColor(Color),
- }
- fn main() {
- let msg = Message::ChangeColor(Color::Hsv(0, 160, 255));
- match msg {
- // 透過 .. 忽略剩餘部分數值
- Message::ChangeColor(Color::Rgb(..,b)) => println!(
- "藍色 {}",
- b
- ),
- // 透過 _ 忽略整個數值
- Message::ChangeColor(Color::Hsv(_, s, _)) => println!(
- "飽和度 {}",
- s
- ),
- // Guards,compiler 無法檢查 if 所有可能性,需搭配 _ =>
- Message::Move{y,..} if y > 0 => println!(
- "移動 y:{}",
- y
- ),
- // @ 綁定
- Message::Move{x: x_variable @ 3..=7, y:_ } => println!(
- "移動 x:{} 在 3~7",
- x_variable
- ),
- // 透過 ..= 配對數值範圍 只允許使用數字或 char 數值
- Message::Move{x: 3..=7, y:_ } => println!(
- "移動 x 在 3~7"
- ),
- // 多重模式
- Message::Quit | Message::Write(_)=> println!(
- "Quit or Write"
- ),
- _ => (),
- }
- }
詳細請參考連結
- #[no_mangle]
- pub extern "C" fn addition(a: u32, b: u32) -> u32 {
- a + b
- }
留言
張貼留言