首页 > 其他分享 >Rust 笔记

Rust 笔记

时间:2023-05-10 13:33:23浏览次数:28  
标签:笔记 var let fn println main Rust

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 三种情况,分别表示小于,大于和等于。

待续

标签:笔记,var,let,fn,println,main,Rust
From: https://www.cnblogs.com/risejl/p/17387723.html

相关文章

  • Lucas 定理学习笔记
    一、定理给定\(n,m,p\),\(p\)是质数,求\(C_{m+n}^n\bmodp\),\(n,m\le10^{18},p\le10^6\)。这题可以用Lucas定理求解。Lucas定理:当\(p\)是个质数时,\(\forallm,n\inN,C_n^m\equivC_{\lfloor\frac{n}{p}\rfloor}^{\lfloor\frac{m}{p}\rfloor}\timesC_{n\bmodp}......
  • sql必知必会笔记
    sql关键字作为保留字使用,不能用于表或者列的名称sql语句不区分大小写sql语句中空格会被忽略select列名之间用逗号分隔少用*号检索,会降低性能distinct关键字作用于所有的列限制结果语法top5关键字sqlserver和access中使用fetchfirst5rowsonlyDB2......
  • 文盘Rust —— rust连接oss | 京东云技术团队
    作者:京东科技贾世闻对象存储是云的基础组件之一,各大云厂商都有相关产品。这里跟大家介绍一下rust与对象存储交到的基本套路和其中的一些技巧。基本连接我们以[S3sdk](https://github.com/awslabs/aws-sdk-rust)为例来说说基本的连接与操作,作者验证过aws、京东云、阿里云。......
  • Effective Modern C++ 学习笔记
    前言记录下阅读此书的感想与总结,一方面能巩固复习,另一方面也能更好地浓缩本书的精华,方便日后的回看。第五章右值引用、移动语义和完美转发它们带来的好处移动语义使得编译器能使用效率更高的移动操作来替换昂贵的复制操作移动语义使得创建只移对象成为可能,如:std::unique_ptr,t......
  • Django笔记二十三之case、when操作条件表达式搜索、更新等操作
    本文首发于公众号:Hunter后端原文链接:Django笔记二十三之条件表达式搜索、更新等操作这一篇笔记将介绍条件表达式,就是如何在model的使用中根据不同的条件筛选数据返回。这个操作类似于数据库中ifelifelse的逻辑。以下是本篇笔记的目录:model和数据准备When和Case......
  • RustDesk 远程桌面
    RustDesk是一款开源远程桌面软件。有云服务器的话,可以几分钟就搭一个,本文是搭建的记录。自建服务器下载服务器程序,#上传进服务器,假设其IP为`x.x.x.x`[email protected]:登录进服务器:#解压unziprustdesk-server-linux-amd64.zip#......
  • 五月第一篇阅读笔记
    人月神话读后感书名《人月神话》中的人指的是人力,月指的是工作时间,主要的意思是人月作为一种衡量软件开发工作量的单位有其误导性,举例来说,1个人可以在10周之内做完的项目,10个人不一定可以在1周之内完成。其实在书中作者更进一步地指出,单纯地增加开发人力,不仅不能对应地减少项目......
  • React笔记-组件(一)
    React学习笔记-组件(一未完成)特点声明式组件化跨平台React脚手架a.全局安装react脚手架create-react-appnpminstallcreate-react-app-g&npxcreate-react-appmy-appb.使用create-react-app创建react应用,如果直接使用npx则无需执行这一步,直接执行第3步c......
  • React笔记-事件(三)
    React学习笔记-事件(三)定义事件React元素的事件处理和DOM元素的很相似但是有一点语法上的不同React事件的命名采用小驼峰式(camelCase)而不是纯小写如点击事件onClickimportReactfrom'react'exportdefaultclasslearnEventextendsReact.Component{///......
  • React笔记-样式(二)
    React学习笔记-样式(二)内联样式importReactfrom"react";exportdefaultclassLearnStyleextendsReact.Component{render(){return(<div>{/*以下两种方法都可以一种不用引号将css以小驼峰方式写另一种加上引号写......