关于rust:Rust-笔记

4次阅读

共计 5755 个字符,预计需要花费 15 分钟才能阅读完成。

The Rust Programming Language

Rust 编程语言笔记。

起源:The Rust Programming Language Book。


装置

应用 rustup 来装置 Rust

Rust 源文件以 .rs 作为扩展名。

几个罕用的命令:

  • 编译:rustc .rs-file
  • 运行:./compiled-file
  • 查看 Rust 编译器版本:rustc --version
  • 查看 rustup 版本:rustup --version
  • 更新 Rust 编译器:rustup update
  • 卸载 Rustrustuprustup self uninstall
  • 本地文档:rustup doc

包管理工具

Rust 的包管理工具是 Cargo

几个罕用的命令:

  • 查看 cargo 的版本:cargo --version
  • 新建我的项目:cargo new
  • 我的项目构建:cargo build
  • 运行我的项目:cargo run
  • 我的项目查看:cargo check:该命令确保我的项目能够编译,但不生成可执行文件,速度比 cargo build 更快

Rust 应用 TOML(Tom's Obvious Minimal Language) 格局来治理依赖。

应用 cargo new 创立新我的项目后,在该项目标目录下会有名为 Cargo.toml 的文件来治理依赖和包。

能够应用 cargo add 来增加依赖,也能够在 .toml 文件的 [dependencies] 字段下增加包名。

例如:

[dependencies]
rand = "0.8.5"

包的版本应用 三位的规范包规范

.rs 文件中应用关键字 use 来导入包。

标准

  • Rust 的缩进采纳的是 4 个 space,而不是 tab
  • Rust 应用 snake case 对变量和函数命名,也就是全副应用小写字母,单词两头应用下划线 _ 连贯,例如:var_name

Hello World

fn main() {println!("Hello, World!");
}
  • fn 是函数(function)的关键词
  • main() 是 Rust 的主函数、相似于 C、C++
  • 每行完结须要用分号 ; 示意

正文

Rust 有三种正文:

  • 单行正文: //
  • 多行正文:/* */
  • 文档(DocString)正文:/** */

变量

Rust 动态 类型语言,在申明变量时须要应用关键词 let 并在冒号 : 后指明变量的类型。这点相似于 Python 的 Type-Hint 以及 TypeScript

let var: u8 = 0;

可修改性

Rust 中的所有变量都有可批改(mutable)或不可修改性(immutable),如果在申明变量时不明确指明,那么默认为不可批改。

应用关键字 mut 示意变量能够批改。

let mut var: u8 = 2;
u8 = 3; // That's OK

let ano_var: u8 = 2;
u8 = 3; // Error

shadowing

fn main() {
    let x: u32 = 5;
      let x = x + 1;
      {
        let x = x * 2;
        println!("The inner x: {x}");
      }
      println!("The outer x: {x}");
}

// The inner x: 12
// The outer x: 6

如上述代码所示:申明了多个名为 x 的变量,在 Rust 中,咱们称 第一个 x 被第二个 x shadow,或者 第二个 x overshadow 了第一个 x,这意味着:当应用 x 这个变量时,编译器总是应用第二个 x,即第二个 x 拿走了第一个 x 的所有,直到程序流来到第二个 x 的作用域或者第二个 x 也被 shadow。

shadow 和 mut 的区别

  1. shadow 使得能够扭转同名变量的类型,然而 mut 会在编译时出错

    fn main() {
        let x: &str = " ";
          let x: usize = x.len(); // 5
      
        let mut x: &str = " ";
        x = x.len()             // Error}
  2. shadow 使得能够批改不可批改的同名变量的值

    fn main() {
        let x: u32 = 5;
        x = 6;             // Error, 因为没有变量默认是不可批改的
        
        let x: u32 = 5;
        let x = 6;
          println!("{}", x)  // 6
    }

常量

Rust 应用 const 关键字申明常量。通常来说,须要用大写字母申明常量。

const THE_DAY_I_START_LEARNING_RUST: String = "2023.5.9";

不可批改的变量和常量的区别在于:

  1. 常量只能是不可批改的,不能通过 mut 关键字使得常亮能够批改
  2. 常量通常只赋值给常量申明的表达式,而不是运行时的计算表达式
  3. 常量能够在任何作用域(scope)中申明,在程序运行期间,在其申明的作用域中是无效的

数据类型

Rust 是动态类型语言,因而在编译时就须要晓得所有的变量类型。

例如在数据转换中:

fn main() {let var = "100".parse().expect("Not a number!"); // Error
    let var: u32 = "100".parse().expect("Not a number"); // OK, var == 100
}

根本类型

Rust 的根本数据类型有 4 种:

  • 布尔 bool
  • 整型 integer
  • 浮点型 float
  • 字符型 char

布尔型

布尔型有两个值:

  1. true
  2. false

整型

整型有 6 种长度,每种长度分类 有符号 无符号 两类。

长度 有符号 无符号
8-bit i8 u8
16-bit i16 u16
32-bit i32 u32
64-bit i64 u64
128-bit i128 u128
arch isize usize

整型字面量(literal)

字面量 举例
十进制 98_222
十六进制 0xff
八进制 0o77
二进制 0b1111_0000
字节(u8) b’A’
  • 整型的默认类型为 i32
  • 在应用汇合类数据类型的索引时,应用 usizeisize

浮点型

浮点型有两类,而且都是有符号的:

  • f32
  • f64:默认类型

字符型

字符型用 c(character)标识。

复合类型

Rust 的复合类型包含:

  • 元组
  • 数组

元组

元组 tuple:用括号 () 申明,元组元素的数据类型能够 不同

元组是 定长 的,一旦申明后就不能扭转大小。

let tup: (u32, f32, bool) = (1, 2.2, true);

Python 不同,Rust 中的元组能够应用 . 运算符来拜访。

let tup: (u32, f32, bool) = (1, 2.2, true);
println!("{}", tup.0); // 1
println!("{}", tup.2); // 2.2
println!("{}", tup.3); // true

数组

数组 array: 用方括号 [] 申明,数组元素的数据类型必须 雷同

数组也是 定长 的。

let arr: [u8; 5] = [1, 2, 3, 4, 5];

; 的前后别离示意数组元素的类型和数组元素的个数。

能够应用索引 [],拜访数组元素,因为数组以定长模式存储在栈中:

let first = arr[0];

管制

条件

if, else if, else 等关键字控制程序流。

Rust 的条件语句不须要外嵌圆括号 (),然而也不同于 Python 的 :,条件执行体须要用花括号:{}

fn main() {
  let var: u32 = 8;
  if var > 0 {println!("{var} is greater than 0!");
  } else if var < 0 {println!("{var} is less than 0!");
  } else {println!("{var} is equal to 0!");
  }
}

注:和 JavaScriptRuby 等语言不同,Rust 语言 不会 在条件判断时主动转换变量的类型,例如:

fn main() {
    let var: bool = true;
  if var == 0 {println!("You can't get there in Rust");
  }
}

循环

Rust 中有 3 种循环:

  • 有限循环 loop
  • while 循环
  • for 循环

完结、跳出循环的关键字:

  • break 跳出以后循环
  • continue 完结本次循环(开始下一次循环)

loop 循环

Rust 能够应用关键字 loop 来创立有限循环,例如:

loop {println!("This is a infinite loop");
}

// 等价于
while true {println!("This is a infinite loop");
}

continueloop 循环有效。

能够用 `nameloop 循环命名(标识符)以跳出多层循环,例如:

fn main() {
  let mut count: u32 = 10;
    `outer: loop {
    let mut remaining: u32 = 2;
    loop {println!("{}", count * remaining);
      remaining -= 1;
      if remaining == 0 {break outer;}
    }
    count -= 1;
    println!("{}", count);
    if count == 0 {break;}
  }
}

while 循环

相似于其余语言的 while 循环。

同样,Rust 的循环条件语句不须要外嵌圆括号 (),然而也不同于 Python 的 :,循环体须要用花括号:{}

fn main() {
  let mut count = 10;
  while count > 0 {println!("{}", count);
    count -= 1;
  }
}

for 循环

for in

for in 循环对遍历对象中的每一个元素都执行遍历:

fn main() {let arr: [u32; 5] = [1, 2, 3, 4, 5];
  for element in arr {println!("{}", element);
  }
}
for range

for range 相似于 Python 的同名函数。

fn main() {
  for i in 0..5 {println!("{}", i);
  }
}

应用 .rev() 倒序输入:

fn main() {for i in (0..5).rev() {println!("{}", i);
  }
}

函数

应用关键字 fn 申明函数,Rust 总是 首先 执行 main 函数。

fn main() {
  let var: u32 = 3;
  increment_and_print(var);
}

fn increment_print(num: u32) -> u32 {
    num += 1;
  println!("{}", num);
  return num;
  // num
}

函数的参数须要申明名称和类型,返回值用 -> 示意,只须要申明类型。

能够应用关键字 return 显式返回值,也能够把返回值写在最初一行(不要应用 ; 结尾)。Rust 默认把最初一行的值作为返回值。

输出和输入

输出

应用规范库 std::io 来导入规范库的 io。

use std::io;

fn main() {let mut inp: String = String::new();
     io::stdin.read_line(&mut inp).expect("Failed to read"); 
  println!("{inp}");
}
  • 应用 stdin 引入规范输出流,
  • 应用 read_line(&) 来读取输出,
  • 应用 expect() 来解决异常情况。

输入

应用 println!() 来输入内容。

println!() 示意调用 macroprintln() 示意调用函数

Rust 不反对间接输入变量的值,必须 格式化(format)后输入。在引号 "" 中使花括号 {} 来输入变量。

fn main() {
    let var: u32 = 15;
      println!("{}", var); // 15
      // println!("var equals {var}")  Also ok!
      // println!(var)  Error!
}

构造体

Rust 的构造体相似于 C,应用关键字 struct 申明。

构造体中的每个元素称为“域”(field),域是可批改的(mutable),应用 . 来拜访域的值。

struct User {
  active: bool,
  sign_in_count: u32,
  username: String,
  email: String
}

fn main() {
  let user = User {
    active: false,
    sign_in_count: 1,
    username: String::from("someusername"),
    email: String::from("someuseremail"),
  };
  
  user1.email = "anotheremail";
}

能够应用 .. 来简化域成员的赋值:

struct User {
  active: bool,
  sign_in_count: u32,
  username: String,
  email: String
}

fn main() {
  let user = User {
    active: false,
    sign_in_count: 1,
    username: String::from("someusername"),
    email: String::from("someuseremail"),
  };
  
  let user_2 = User {
    active: true,
    ..user1
  }
}

下面的代码示意,除了域 active 之外,user_2 的其余域值和 user 相等。

注:..user 后没有 ,

枚举

例如上面的代码:

use std::cmp::Ordering;
use std:io;

fn main() {println!("This is a guessing game");
      const SECRET_NUMBER: u32 = 12;
      let mut guess: String = String::new();
      println!("Enter your guess:");
      io::stdin.read_line(&mut guess).expect("Failed to read line");
      let mut guess = match guess.parse().wrap() {Ok(num) => num,
      Err(_) => {println!("You should enter a number!");
      }
      }
      match guess.cmp::Ordering {Less => println!("Too small!"),
      Greater => println!("Too big!"),
      Equal => println!("You are the winner!");
  }
}

match 关键字用于开始匹配枚举。

这段代码中用到了两个 枚举 类型,别离是:

  1. guess 的类型判断会返回枚举类型 Result,它有 OkErr 两个枚举值,别离示意胜利和谬误两种状况
  2. guessSECRET_NUMBER 两个值之间的比拟会返回枚举类型 Ordering,它有 LessGreaterEqual 三种状况,别离示意小于,大于和等于。

待续

正文完
 0