rust学习(一)基础概念

Li Guangqiao - 13/05/2023

Rust

Rust相关知识的思维导图

rust知识大纲

浅入Rust基础

目标:首先总结归纳Rust的基本内容,接着每天回顾一个了解过的rust基础

常用语法

变量和可变性

数据类型

标量类型

标量类型

整型

Rust的整型类型根据长度划分有6类和有字符和无字符组合起来一共有12中整型类型如下图:

整型分类

每一种存储类型的存储空间的计算公式(除了arch类型): $$ -(2^{n-1})\ \ to\ \ 2^{n-1}-1 $$ 注意

arch类型取决于计算机架构,64位架构对应n = 64,32位架构对应n = 32。

浮点型
let x = 1.0; //默认f64
let y:f32 = 2.0; //声明类型f32
数值操作

数值操作主要包括增、删、改、查和取余。

// addition
    let sum = 5 + 10;

    // subtraction
    let difference = 95.5 - 4.3;

    // multiplication
    let product = 4 * 30;

    // division
    let quotient = 56.7 / 32.2;
    let truncated = -5 / 3; // Results in -1

    // remainder
    let remainder = 43 % 5;
布尔类型

布尔类型的只有两个值:true和false。

布尔类型只有一个字节。

在Rust中实际是使用bool比如:

let t = true;
let f:bool = false;

布尔类型的主要作用是条件判断。比如控制流中的if表达式

字符类型

Rust 的char 类型是该语言最基础的字母类型例如:

fn main() {
    let c = 'z';
    let z: char = ''; // with explicit type annotation
    let heart_eyed_cat = '😻';
}

注意:

字符字面量使用单引号,而字符串字面量使用双引号

Rust的字符类型大小是4字节而且代表Unicode标量值。这意味着它可以表示的不仅仅是ASCII。重音字母;中文、日文、韩文;emoji;和零宽度空格在Rust中都是有效的字符值.

复合类型

复合类型的目标场景:可以将多个值组到一个类型中。

Rust 拥有两个原始复合类型

  1. 元组
  2. 数组
元组

元组是一种将多种类型的值组合成一种复合类型的通用方法。

元组有固定的长度:一旦声明,它们就不能增大或缩小

例如:

let tup:(i32,f64,u8) = (500,6.4,1);

元组解构

//声明元组
let tup = (500,6.4,1);
let (x,y,z) = tup;
println!("x = {}\n y = {} \n z = {}",x,y,z);
fn main() {
    let x: (i32, f64, u8) = (500, 6.4, 1);

    let five_hundred = x.0;

    let six_point_four = x.1;

    let one = x.2;
    println!("x = {}\n y = {} \n z = {}",five_hundred,six_point_four,one);
}

空元组拥有一个特殊的名字unit,这个值写作**()**代表元组空值类型位一个空的返回类型。

数组

数组的声明

let a = [1,2,3,4,5];

注意:

  1. 如果你希望在堆栈上分配数据而不是直接在堆上分配,数组非常有用的。

  2. 当你确保你的元素是具有固定长度时,数组非常有用。

  3. 但数组并没有像容器(Vector)那样,大小可以灵活的增加或者减少

  4. 然而数组对于固定长度且不需要变化的固定值集合更有用比如:月份数组

let months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

声明类型和长度

$$ let\ 变量名:[成员类型;数组长度] = [成员1,成员2,...] $$

//声明类型和长度
let a:[i32;5] = [1,2,3,4,5];

快速声明元素相同的数组

$$ let\ 变量名:[成员值;数组长度]; $$

let a = [3;5]
// a = [3,3,3,3,3]

有效数组访问机制:通过数组索引去访问,但索引不能超过数组的长度。

函数

参数

Rust函数的参数声明

//()括号内容声明参数名和参数类型
fn test_fn(x:i32){
    
}
fn main(){
    test_fn(5);
}
语句和表达式

函数体内容由一系列语句组成,并可选择性的使用表达式作为返回值。

注意: Rust 是一门基于表达式的语言,这也是Rust特有的部分,其他语言并没有相同的规则。

**语句:**语句是执行某些操作但不返回值的指令

**表达式:**表达式实际上指的是表达式的结果值

let y = 6; //statement
let z = {
    let x = 3;
    x+2 //expression
}//expression
// y = 6,z=5
函数返回值

函数返回值声明 $$ fn 函数名() -> 返回值类型 $$

使用return返回

fn test_fn() -> i32 {
 	return  5;
}

使用表达式返回

fn test_fn() -> i32 {
    5
}
fn test_one(x:i32) -> i32{
    x+1
}

注释

// 单行注释
/**
*注释块
*/

控制流

if 表达式

if表达式的存在主要是为了分支判断处理例如:

fn main() {
    let number = 3;

    if number < 5 {
        println!("condition was true");
    } else {
        println!("condition was false");
    }
}

在let语句中使用if

let condition = 5>3;
let number = if condition {
    5
} else {
    3
}
println!("{number}");
//println!("{}",number);

注意:

原理:Rust中变量类型是单一的。

故当if和else返回的值类型不一致时会报错,例如:

let condition = true;

let number = if condition { 5 } else { "six" };

println!("The value of number is: {number}");
loop循环体
//死循环
loop{
    println!("again!");
}

利用循环体返回值

$$ break + 语句 $$

let mut counter = 0;
let result = loop {
    counter += 1;
    if counter == 10{
        //break 后可以添加循环的返回值
        break counter * 2;
    }
};
循环标签

循环体允许添加循环体标签,目的是消除多个循环之间的歧义。

例如:

fn main() {
    let mut count = 0;
    'counting_up: loop {
        println!("count = {count}");
        let mut remaining = 10;

        loop {
            println!("remaining = {remaining}");
            if remaining == 9 {
                break;
            }
            if count == 2 {
                break 'counting_up;
            }
            remaining -= 1;
        }

        count += 1;
    }
    println!("End count = {count}");
}

while+循环条件

循环条件为真,执行循环体

fn main() {
    let mut number = 3;

    while number != 0 {
        println!("{number}!");

        number -= 1;
    }

    println!("LIFTOFF!!!");
}

循环一个数组

fn main() {
    let a = [10, 20, 30, 40, 50];
    let mut index = 0;

    while index < 5 {
        println!("the value is: {}", a[index]);

        index += 1;
    }
}
集合的for循环

数组换成for循环

fn main() {
    let a = [10, 20, 30, 40, 50];
    let mut index = 0;

    for index in 0..5 {
        println!("the value is: {}", a[index]);
    }
}

增强for循环:可以避免越界问题

fn main() {
    let a = [10, 20, 30, 40, 50];

    for item in a {
        println!("the value is: {}", item);
    }
}

另一种避免循环越界的方式是倒序循环

fn main() {
    //rev方法是将数组(1..4)倒序遍历
    //前闭后开
    for number in (1..4).rev() {
        println!("{number}!");
    }
    println!("LIFTOFF!!!");
}
Li Guangqiao
Li Guangqiao

一个正在转rust的ExtJs前端工程师。迷信rust的整体发展,十分相信rust在各个领域都能发光发热,至少目前rust在很多领域上验证了其安全性、易维护性。但说实话对于我这种菜鸡也是真的难上手哈哈哈~~。 思路总结:

  • 万物诞生都会有一个需求来源,每一个改变都是为了解决某个问题,最后应该考虑如何去做
  • 学会掌握一些宏观的知识和理论:系统论、还原论
  • 工程化思想,如何描述整体,从整体架构到模块关联等 故学习东西应该像看地图一样,先看整体了解整体的结构,然后再聚焦每一个模块,对于模块的学习,思考三个问题,“是什么?”、“为什么?”、“怎么做?”;那么设计一个东西时也应该去考虑整体性和关联性。

有关于未来的发展,以下是鄙人的粗浅的观点:

  • 编程语言未来应该是每个人必备的工具
  • 未来的交互方式应该会以语言交互为主流
  • 下一个去中心化的技术方案出来之前,区块链依然是web3建立价值体系的基础技术方案,如何将现实价值和虚拟价值联通是进入数字世界的一个大难题。
  • 未来注定是AI的世界。AI的进化会伴随绝大部分人的退化,届时除了尖端人才,人们学习的重心会放在何处?