偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

半小時(shí)入門(mén)Rust,這是一篇Rust代碼風(fēng)暴

新聞 前端
據(jù)說(shuō)很多開(kāi)發(fā)者一天入門(mén) Python,兩天上手 Go,但到了 Rust 就會(huì)發(fā)現(xiàn)畫(huà)風(fēng)隱約有些不對(duì)。它從語(yǔ)法到特性,似乎都要復(fù)雜一些。本文介紹的就是 Rust,作者表示,通過(guò)解析大量代碼,「半個(gè)小時(shí)」就能入門(mén) Rust。

據(jù)說(shuō)很多開(kāi)發(fā)者一天入門(mén) Python,兩天上手 Go,但到了 Rust 就會(huì)發(fā)現(xiàn)畫(huà)風(fēng)隱約有些不對(duì)。它從語(yǔ)法到特性,似乎都要復(fù)雜一些。本文介紹的就是 Rust,作者表示,通過(guò)解析大量代碼,「半個(gè)小時(shí)」就能入門(mén) Rust。

[[318599]]

Rust 是一門(mén)系統(tǒng)編程語(yǔ)言,專(zhuān)注于安全,尤其是并發(fā)安全。它支持函數(shù)式和命令式以及泛型等編程范式的多范式語(yǔ)言,且 TensorFlow 等深度學(xué)習(xí)框架也把它作為一個(gè)優(yōu)秀的前端語(yǔ)言。

Rust 在語(yǔ)法上和 C、C++類(lèi)似,都由花括弧限定代碼塊,并有相同的控制流關(guān)鍵字,但 Rust 設(shè)計(jì)者想要在保證性能的同時(shí)提供更好的內(nèi)存安全。Rust 自 2016 年就已經(jīng)開(kāi)源了,在各種開(kāi)發(fā)者調(diào)查中,它也總能獲得「最受歡迎的語(yǔ)言」這一稱(chēng)贊,目前該開(kāi)源項(xiàng)目已有 42.9K 的 Star 量。

機(jī)器之心的讀者大多數(shù)都非常熟悉 Python,而 Rust 就沒(méi)那么熟悉了。在 Amos 最近的一篇博文中,他表示如果閱讀他的作品,我們半個(gè)小時(shí)就能入門(mén) Rust。因此在這篇文章中,我們將介紹該博文的主要內(nèi)容,它并不關(guān)注于 1 個(gè)或幾個(gè)關(guān)鍵概念,相反它希望通過(guò)代碼塊縱覽 Rust 的各種特性,包括各種關(guān)鍵詞與符號(hào)的意義。

在 HackNews 上,很多開(kāi)發(fā)者表示這一份入門(mén)教程非常實(shí)用,Rust 的入門(mén)門(mén)檻本來(lái)就比較高,如果再介紹各種復(fù)雜的概念與特性,很容易出現(xiàn)「從入門(mén)到勸退」。因此這種從實(shí)例代碼出發(fā)的教程,非常有意義。

從變量說(shuō)起

let 能綁定變量:

  1. let x; // declare "x" 
  2.  
  3. x = 42// assign 42 to "x" 
  4.  
  5. let x = 42// combined in one line 

可以使用 :來(lái)制定變量的數(shù)據(jù)類(lèi)型,以及數(shù)據(jù)類(lèi)型注釋?zhuān)?/p>

  1. let x: i32; // `i32` is a signed 32-bit integer 
  2.  
  3. x = 42
  4.  
  5. // there's i8, i16, i32, i64, i128 
  6.  
  7. // also u8, u16, u32, u64, u128 for unsigned 
  8.  
  9. let x: i32 = 42// combined in one line 

如果你聲明一個(gè)變量并在初始化之前就調(diào)用它,編譯器會(huì)報(bào)錯(cuò):

  1. let x; 
  2.  
  3. foobar(x); // error: borrow of possibly-uninitialized variable: `x` 
  4.  
  5. x = 42

然而,這樣做完全沒(méi)問(wèn)題:

  1. let x; 
  2.  
  3. x = 42
  4.  
  5. foobar(x); // the type of `x` will be inferred from here 

下劃線(xiàn)表示特殊的命名,或者更確切地說(shuō)是「缺失的命名」,它和 Python 的用法有點(diǎn)像:

  1. // this does *nothing* because 42 is a constant 
  2.  
  3. let _ = 42
  4.  
  5. // this calls `get_thing` but throws away its result 
  6.  
  7. let _ = get_thing(); 

以下劃線(xiàn)開(kāi)頭的命名是常規(guī)命名,只是編譯器不會(huì)警告它們未被使用:

  1. // we may use `_x` eventually, but our code is a work-in-progress 
  2.  
  3. // and we just wanted to get rid of a compiler warning for now. 
  4.  
  5. let _x = 42

相同命名的單獨(dú)綁定是可行的,第一次綁定的變量會(huì)取消:

  1. let x = 13
  2.  
  3. let x = x + 3
  4.  
  5. // using `x` after that line only refers to the second `x`, 
  6.  
  7. // the first `x` no longer exists. 

Rust 有元組類(lèi)型,可以將其看作是「不同數(shù)據(jù)類(lèi)型值的定長(zhǎng)集合」。

  1. let pair = ('a'17); 
  2.  
  3. pair.0// this is 'a' 
  4.  
  5. pair.1// this is 17 

如果真的想配置 pair 的數(shù)據(jù)類(lèi)型,可以這么寫(xiě):

  1. let pair: (char, i32) = ('a'17); 

元組在賦值時(shí)可以被拆解,這意味著它們被分解成各個(gè)字段:

  1. let (some_char, some_int) = ('a'17); 
  2.  
  3. // now, `some_char` is 'a', and `some_int` is 17 

當(dāng)一個(gè)函數(shù)返還一個(gè)元組時(shí)會(huì)非常有用:

  1. let (left, right) = slice.split_at(middle); 

當(dāng)然,在解構(gòu)一個(gè)元組時(shí),可以只分離它的一部分:

  1. let (_, right) = slice.split_at(middle); 

分號(hào)表示語(yǔ)句的結(jié)尾:

  1. let x = 3
  2.  
  3. let y = 5
  4.  
  5. let z = y + x; 

不加分號(hào)意味著語(yǔ)句可以跨多行:

  1. let x = vec![12345678
  2.  
  3. .iter() 
  4.  
  5. .map(|x| x + 3
  6.  
  7. .fold(0, |x, y| x + y); 

函數(shù)來(lái)了

fn 聲明一個(gè)函數(shù)。下面是一個(gè)空函數(shù):

  1. fn greet() { 
  2.  
  3. println!("Hi there!"); 
  4.  

這是一個(gè)返還 32 位帶符號(hào)整數(shù)值的函數(shù)。箭頭表示返還類(lèi)型:

  1. fn fair_dice_roll() -> i32 { 
  2.  
  3. 4 
  4.  

花括號(hào)表示了一個(gè)代碼塊,且擁有其自己的作用域:

  1. // This prints "in", then "out" 
  2.  
  3. fn main() { 
  4.  
  5. let x = "out"
  6.  
  7.  
  8. // this is a different `x` 
  9.  
  10. let x = "in"
  11.  
  12. println!(x); 
  13.  
  14.  
  15. println!(x); 
  16.  

代碼塊也是表示式,表示其計(jì)算為一個(gè)值。

  1. // this: 
  2.  
  3. let x = 42
  4.  
  5. // is equivalent to this: 
  6.  
  7. let x = { 42 }; 

在一個(gè)代碼塊中,可以有多個(gè)語(yǔ)句:

  1. let x = { 
  2.  
  3. let y = 1// first statement 
  4.  
  5. let z = 2// second statement 
  6.  
  7. y + z // this is the *tail* - what the whole block will evaluate to 
  8.  
  9. }; 

這也是為什么「省略函數(shù)末尾的分號(hào)」等同于加上了 Retrun,這些都是等價(jià)的:

  1. fn fair_dice_roll() -> i32 { 
  2.  
  3. return 4
  4.  
  5.  
  6. fn fair_dice_roll() -> i32 { 
  7.  
  8. 4 
  9.  

if 條件語(yǔ)句也是表達(dá)式:

  1. fn fair_dice_roll() -> i32 { 
  2.  
  3. if feeling_lucky { 
  4.  
  5. 6 
  6.  
  7. else { 
  8.  
  9. 4 
  10.  
  11.  

match 匹配器也是一個(gè)表達(dá)式:

  1. fn fair_dice_roll() -> i32 { 
  2.  
  3. match feeling_lucky { 
  4.  
  5. true => 6
  6.  
  7. false => 4
  8.  
  9.  

Dots 通常用于訪問(wèn)某個(gè)對(duì)象的字段:

  1. let a = (1020); 
  2.  
  3. a.0// this is 10 
  4.  
  5. let amos = get_some_struct(); 
  6.  
  7. amos.nickname; // this is "fasterthanlime" 

或者調(diào)用對(duì)象的方法:

  1. let nick = "fasterthanlime"
  2.  
  3. nick.len(); // this is 14 

雙冒號(hào)與此類(lèi)似,但可對(duì)命名空間進(jìn)行操作。在此舉例中,std 是一個(gè) crate (~ a library),cmp 是一個(gè) module(~ a source file),以及 min 是個(gè)函數(shù):

  1. let least = std::cmp::min(38); // this is 3 

use 指令可用于從其他命名空間中「引入范圍」命名:

  1. use std::cmp::min; 
  2.  
  3. let least = min(71); // this is 1 

在 use 指令中,花括號(hào)還有另一個(gè)含義:「globs」,因此可以同時(shí)導(dǎo)入 min 以及 max:

  1. // this works: 
  2.  
  3. use std::cmp::min; 
  4.  
  5. use std::cmp::max; 
  6.  
  7. // this also works: 
  8.  
  9. use std::cmp::{min, max}; 
  10.  
  11. // this also works! 
  12.  
  13. use std::{cmp::min, cmp::max}; 

通配符(*)允許從命名空間導(dǎo)入符號(hào):

  1. // this brings `min` and `max` in scope, and many other things 
  2.  
  3. use std::cmp::*; 

Types 也是命名空間和方法,它可以作為常規(guī)函數(shù)調(diào)用:

  1. let x = "amos".len(); // this is 4 
  2.  
  3. let x = str::len("amos"); // this is also 4 

str 是一個(gè)基元數(shù)據(jù)類(lèi)型,但在默認(rèn)情況下,許多非基元數(shù)據(jù)類(lèi)型也在作用域中。

  1. // `Vec` is a regular struct, not a primitive type 
  2.  
  3. let v = Vec::new(); 
  4.  
  5. // this is exactly the same code, but with the *full* path to `Vec` 
  6.  
  7. let v = std::vec::Vec::new() 

至于為什么可行,因?yàn)?Rust 在每個(gè)模塊的開(kāi)頭都插入了:

  1. use std::prelude::v1::*; 

再說(shuō)說(shuō)結(jié)構(gòu)體

使用 struct 關(guān)鍵字聲明結(jié)構(gòu)體:

  1. struct Vec2 { 
  2.  
  3. x: f64, // 64-bit floating point, aka "double precision" 
  4.  
  5. y: f64, 
  6.  

可以使用結(jié)構(gòu)語(yǔ)句初始化:

  1. let v1 = Vec2 { x: 1.0, y: 3.0 }; 
  2.  
  3. let v2 = Vec2 { y: 2.0, x: 4.0 }; 
  4.  
  5. // the order does not matter, only the names do 

有一個(gè)快捷方式可以從另一個(gè)結(jié)構(gòu)體初始化本結(jié)構(gòu)體的其余字段:

  1. let v3 = Vec2 { 
  2.  
  3. x: 14.0
  4.  
  5. ..v2 
  6.  
  7. }; 

這就是所謂的「結(jié)構(gòu)體更新語(yǔ)法」只能發(fā)生在最后一個(gè)位置,不能在其后面再跟一個(gè)逗號(hào)。

注意其余字段可以表示所有字段:

  1. let v4 = Vec2 { ..v3 }; 

結(jié)構(gòu)體與元組一樣,可以被解構(gòu)。例如一個(gè)有效的 let 模式:

  1. let (left, right) = slice.split_at(middle); 
  2.  
  3. let v = Vec2 { x: 3.0, y: 6.0 }; 
  4.  
  5. let Vec2 { x, y } = v; 
  6.  
  7. // `x` is now 3.0, `y` is now `6.0` 
  8.  
  9. let Vec2 { x, .. } = v; 
  10.  
  11. // this throws away `v.y` 

讓 let 模式在 if 里可以作為條件:

  1. struct Number { 
  2.  
  3. odd: bool, 
  4.  
  5. value: i32, 
  6.  
  7.  
  8. fn main() { 
  9.  
  10. let one = Number { odd: true, value: 1 }; 
  11.  
  12. let two = Number { odd: false, value: 2 }; 
  13.  
  14. print_number(one); 
  15.  
  16. print_number(two); 
  17.  
  18.  
  19. fn print_number(n: Number) { 
  20.  
  21. if let Number { odd: true, value } = n { 
  22.  
  23. println!("Odd number: {}", value); 
  24.  
  25. else if let Number { odd: false, value } = n { 
  26.  
  27. println!("Even number: {}", value); 
  28.  
  29.  
  30.  
  31. // this prints: 
  32.  
  33. // Odd number: 1 
  34.  
  35. // Even number: 2 

多分支的 match 也是條件模式,就像 if let:

  1. fn print_number(n: Number) { 
  2.  
  3. match n { 
  4.  
  5. Number { odd: true, value } => println!("Odd number: {}", value), 
  6.  
  7. Number { odd: false, value } => println!("Even number: {}", value), 
  8.  
  9.  
  10.  
  11. // this prints the same as before 

match 必須是囊括所有情況的的:至少需要匹配一個(gè)條件分支。

  1. fn print_number(n: Number) { 
  2.  
  3. match n { 
  4.  
  5. Number { value: 1, .. } => println!("One"), 
  6.  
  7. Number { value: 2, .. } => println!("Two"), 
  8.  
  9. Number { value, .. } => println!("{}", value), 
  10.  
  11. // if that last arm didn't exist, we would get a compile-time error 
  12.  
  13.  

如果非常難實(shí)現(xiàn),_ 那么可以作用一個(gè)“包羅萬(wàn)象”的模式:

  1. fn print_number(n: Number) { 
  2.  
  3. match n.value { 
  4.  
  5. 1 => println!("One"), 
  6.  
  7. 2 => println!("Two"), 
  8.  
  9. _ => println!("{}", n.value), 
  10.  
  11.  

Type 別名

我們可以使用 type 關(guān)鍵字聲明另一類(lèi)型的別名,然后就可以像使用一個(gè)真正的類(lèi)型一樣使用這種類(lèi)型。例如定義 Name 這種數(shù)據(jù)類(lèi)型為字符串,后面就可以直接使用 Name 這種類(lèi)型了。

你可以在方法中聲明不同的數(shù)據(jù)類(lèi)型:

  1. struct Number { 
  2.  
  3. odd: bool, 
  4.  
  5. value: i32, 
  6.  
  7.  
  8. impl Number { 
  9.  
  10. fn is_strictly_positive(self) -> bool { 
  11.  
  12. self.value > 0 
  13.  
  14.  

然后就如同往常那樣使用:

  1. fn main() { 
  2.  
  3. let minus_two = Number { 
  4.  
  5. odd: false
  6.  
  7. value: -2
  8.  
  9. }; 
  10.  
  11. println!("positive? {}", minus_two.is_strictly_positive()); 
  12.  
  13. // this prints "positive? false" 
  14.  

默認(rèn)情況下,聲明變量后它就就是不可變的,如下 odd 不能被重新賦值:

  1. fn main() { 
  2.  
  3. let n = Number { 
  4.  
  5. odd: true
  6.  
  7. value: 17
  8.  
  9. }; 
  10.  
  11. n.odd = false// error: cannot assign to `n.odd`, 
  12.  
  13. // as `n` is not declared to be mutable 
  14.  

不可變的變量聲明,其內(nèi)部也是不可變的,它也不能重新分配值:

  1. fn main() { 
  2.  
  3. let n = Number { 
  4.  
  5. odd: true
  6.  
  7. value: 17
  8.  
  9. }; 
  10.  
  11. n = Number { 
  12.  
  13. odd: false
  14.  
  15. value: 22
  16.  
  17. }; // error: cannot assign twice to immutable variable `n` 
  18.  

mut 可以使變量聲明變?yōu)榭勺兊模?/p>

  1. fn main() { 
  2.  
  3. let mut n = Number { 
  4.  
  5. odd: true
  6.  
  7. value: 17
  8.  
  9.  
  10. n.value = 19// all good 
  11.  

Traits 描述的是多種數(shù)據(jù)類(lèi)型的共同點(diǎn):

  1. trait Signed { 
  2.  
  3. fn is_strictly_negative(self) -> bool; 
  4.  

我們可以在我們定義的 Type 類(lèi)型中定義 Traits:

  1. impl Signed for Number { 
  2.  
  3. fn is_strictly_negative(self) -> bool { 
  4.  
  5. self.value < 0 
  6.  
  7.  
  8.  
  9. fn main() { 
  10.  
  11. let n = Number { odd: false, value: -44 }; 
  12.  
  13. println!("{}", n.is_strictly_negative()); // prints "true" 
  14.  

外部類(lèi)型(foreign type)中定義的 Trait:

  1. impl Signed for i32 { 
  2.  
  3. fn is_strictly_negative(self) -> bool { 
  4.  
  5. self < 0 
  6.  
  7.  
  8.  
  9. fn main() { 
  10.  
  11. let n: i32 = -44
  12.  
  13. println!("{}", n.is_strictly_negative()); // prints "true" 
  14.  

impl 模塊通常會(huì)帶有一個(gè) Type 類(lèi)型,所以在模塊內(nèi),Self 就表示該類(lèi)型:

  1. impl std::ops::Neg for Number { 
  2.  
  3. type Output = Self; 
  4.  
  5. fn neg(self) -> Self { 
  6.  
  7. Self { 
  8.  
  9. value: -self.value, 
  10.  
  11. odd: self.odd, 
  12.  
  13.  
  14.  

有一些traits只是作為標(biāo)記,它們并不是說(shuō) Type 類(lèi)型實(shí)現(xiàn)了某些方法,它只是表明某些東西能通過(guò)Type類(lèi)型完成。例如,i32 實(shí)現(xiàn)了Copy,那么以下代碼就是可行的:

  1. fn main() { 
  2.  
  3. let a: i32 = 15
  4.  
  5. let b = a; // `a` is copied 
  6.  
  7. let c = a; // `a` is copied again 
  8.  

下面的代碼也是能運(yùn)行的:

  1. fn print_i32(x: i32) { 
  2.  
  3. println!("x = {}", x); 
  4.  
  5.  
  6. fn main() { 
  7.  
  8. let a: i32 = 15
  9.  
  10. print_i32(a); // `a` is copied 
  11.  
  12. print_i32(a); // `a` is copied again 
  13.  

但是 Number 的結(jié)構(gòu)體并不能用于 Copy,所以下面的代碼會(huì)報(bào)錯(cuò):

  1. fn main() { 
  2.  
  3. let n = Number { odd: true, value: 51 }; 
  4.  
  5. let m = n; // `n` is moved into `m` 
  6.  
  7. let o = n; // error: use of moved value: `n` 
  8.  

同樣下面的代碼也不會(huì) Work:

  1. fn print_number(n: Number) { 
  2.  
  3. println!("{} number {}"if n.odd { "odd" } else { "even" }, n.value); 
  4.  
  5.  
  6. fn main() { 
  7.  
  8. let n = Number { odd: true, value: 51 }; 
  9.  
  10. print_number(n); // `n` is moved 
  11.  
  12. print_number(n); // error: use of moved value: `n` 
  13.  

但是如果print_number有一個(gè)不可變r(jià)eference,那么 Copy 就是可行的:

  1. fn print_number(n: &Number) { 
  2.  
  3. println!("{} number {}"if n.odd { "odd" } else { "even" }, n.value); 
  4.  
  5.  
  6. fn main() { 
  7.  
  8. let n = Number { odd: true, value: 51 }; 
  9.  
  10. print_number(&n); // `n` is borrowed for the time of the call 
  11.  
  12. print_number(&n); // `n` is borrowed again 
  13.  

如果函數(shù)采用了可變r(jià)eference,那也是可行的,只不過(guò)需要在變量聲明中帶上 mut。

  1. fn invert(n: &mut Number) { 
  2.  
  3. n.value = -n.value; 
  4.  
  5.  
  6. fn print_number(n: &Number) { 
  7.  
  8. println!("{} number {}"if n.odd { "odd" } else { "even" }, n.value); 
  9.  
  10.  
  11. fn main() { 
  12.  
  13. // this time, `n` is mutable 
  14.  
  15. let mut n = Number { odd: true, value: 51 }; 
  16.  
  17. print_number(&n); 
  18.  
  19. invert(&mut n); // `n is borrowed mutably - everything is explicit 
  20.  
  21. print_number(&n); 
  22.  

Copy 這類(lèi)標(biāo)記型的traits并不帶有方法:

  1. // note: `Copy` requires that `Clone` is implemented too 
  2.  
  3. impl std::clone::Clone for Number { 
  4.  
  5. fn clone(&self) -> Self { 
  6.  
  7. Self { ..*self } 
  8.  
  9.  
  10.  
  11. impl std::marker::Copy for Number {} 

現(xiàn)在 Clone 仍然可以用于:

  1. fn main() { 
  2.  
  3. let n = Number { odd: true, value: 51 }; 
  4.  
  5. let m = n.clone(); 
  6.  
  7. let o = n.clone(); 
  8.  

但是Number的值將不會(huì)再移除:

  1. fn main() { 
  2.  
  3. let n = Number { odd: true, value: 51 }; 
  4.  
  5. let m = n; // `m` is a copy of `n` 
  6.  
  7. let o = n; // same. `n` is neither moved nor borrowed. 
  8.  

有一些traits很常見(jiàn),它們可以通過(guò)使用derive 屬性自動(dòng)實(shí)現(xiàn):

  1. #[derive(Clone, Copy)] 
  2.  
  3. struct Number { 
  4.  
  5. odd: bool, 
  6.  
  7. value: i32, 
  8.  
  9.  
  10. // this expands to `impl Clone for Number` and `impl Copy for Number` blocks. 

看上去,整篇教程都在使用大量代碼解釋 Rust 的各種語(yǔ)句與用法??赡芪覀儠?huì)感覺(jué)博客結(jié)構(gòu)不是太明確,但是實(shí)例驅(qū)動(dòng)的代碼學(xué)習(xí)確實(shí)更加高效。尤其是對(duì)于那些有一些編程基礎(chǔ)的同學(xué),他們可以快速抓住 Rust 語(yǔ)言的特點(diǎn)與邏輯。

最后,這篇文章并沒(méi)有展示博客所有的內(nèi)容,如果讀者想真正入門(mén) Rust 語(yǔ)言,推薦可以查閱原博客。

 

 

責(zé)任編輯:張燕妮 來(lái)源: 機(jī)器之心
相關(guān)推薦

2023-11-28 08:29:31

Rust內(nèi)存布局

2022-05-08 16:42:27

Rust編程語(yǔ)言

2022-03-10 16:51:46

C語(yǔ)言代碼if語(yǔ)句

2024-06-27 11:08:45

2023-09-21 11:39:29

RustJetBrainsIDE

2019-10-22 18:00:00

MySQL基礎(chǔ)入門(mén)數(shù)據(jù)庫(kù)

2019-12-13 16:19:15

戴爾

2023-04-20 08:00:00

ES搜索引擎MySQL

2023-06-19 14:14:24

Rust程序Web

2020-09-25 08:10:55

Rust系統(tǒng)編程

2024-04-11 13:13:27

2022-07-25 11:10:58

Rust教程編程語(yǔ)言

2020-03-09 11:43:35

RustCargo編程語(yǔ)言

2024-04-22 08:06:34

Rust語(yǔ)言

2024-11-08 09:19:28

2023-05-29 16:25:59

Rust函數(shù)

2025-01-03 09:12:11

2020-09-01 07:50:21

Rust 編程語(yǔ)言

2022-07-06 07:57:37

Zookeeper分布式服務(wù)框架

2024-06-17 09:00:08

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)