Rust入坑之旅-基础扫盲

Rust入坑之旅-基础扫盲

Scroll Down

image.png

特性

Rust致力于成为优雅解决高并发和高安全性系统问题的编程语言 [18] ,适用于大型场景,即创造维护能够保持大型系统完整的边界。这就导致了它强调安全,内存布局控制和并发的特点。标准Rust性能与标准C++性能不相上下。

环境安装

在 Linux 或 mac 上安装 rustup
打开终端并输入如下命令:

$ curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh

此命令下载一个脚本并开始安装 rustup 工具,这会安装最新稳定版Rust。过程中可能会提示你输入密码。如果安装成功,将会出现如下内容:

Rust is installed now. Great!

更新和卸载

通过 rustup 安装了 Rust 之后,很容易更新到最新版本。在 shell 中运行如下更新脚本:

$ rustup update

为了卸载 Rust 和 rustup,在 shell 中运行如下卸载脚本:

$ rustup self uninstall

检查是否正确安装了 Rust
打终端并运行如下行:

$ rustc --version
rustc x.y.z (abcabcabc yyyy-mm-dd)
cargo --version
cargo 1.57.0 (b2e52d7ca 2021-10-21)

你应能看到已发布的最新稳定版的版本号、提交哈希和提交日期,显示为如下格式:如果出现这些内容,Rust 就安装成功了!Cargo 是 Rust 的构建系统和包管理器 比如构建代码、下载依赖库并编译这些依赖,官方安装包自带了 Cargo,所以上面的执行cargo --version 是可以正常输出的

Hello, world

使用cargo新建项目,会在当前目前生成一个project

cargo new hello_cargo

image.png

  • Cargo.toml

    类似go.mod,pom.xml依赖管理文件

  • src

    存放源代码

  • target

    编译产物

  • Cargo.lock

    用来存放对依赖的变更,类似go.sum
    常用的命令

编译
cargo build
运行
cargo run
检查代码确保其可以编译
cargo check

关键字

  • as - 强制类型转换,消除特定包含项的 trait 的歧义,或者对 use 和 extern crate 语句中的项重命名
  • break - 立刻退出循环
  • const - 定义常量或不变裸指针(constant raw pointer)
  • continue - 继续进入下一次循环迭代
  • crate - 链接(link)一个外部 crate 或一个代表宏定义的 crate 的宏变量
  • dyn - 动态分发 trait 对象
  • else - 作为 if 和 if let 控制流结构的 fallback
  • enum - 定义一个枚举
  • extern - 链接一个外部 crate 、函数或变量
  • false - 布尔字面值 false
  • fn - 定义一个函数或 函数指针类型 (function pointer type)
  • for - 遍历一个迭代器或实现一个 trait 或者指定一个更高级的生命周期
  • if - 基于条件表达式的结果分支
  • impl - 实现自有或 trait 功能
  • in - for 循环语法的一部分
  • let - 绑定一个变量
  • loop - 无条件循环
  • match - 模式匹配
  • mod - 定义一个模块
  • move - 使闭包获取其所捕获项的所有权
  • mut - 表示引用、裸指针或模式绑定的可变性
  • pub - 表示结构体字段、impl 块或模块的公有可见性
  • ref - 通过引用绑定
  • return - 从函数中返回
  • Self - 实现 trait 的类型的类型别名
  • self - 表示方法本身或当前模块
  • static - 表示全局变量或在整个程序执行期间保持其生命周期
  • struct - 定义一个结构体
  • super - 表示当前模块的父模块
  • trait - 定义一个 trait
  • true - 布尔字面值 true
  • type - 定义一个类型别名或关联类型
  • unsafe - 表示不安全的代码、函数、trait 或实现
  • use - 引入外部空间的符号
  • where - 表示一个约束类型的从句
  • while - 基于一个表达式的结果判断是否进行循环
    保留做将来使用的关键字

如下关键字没有任何功能,不过由 Rust 保留以备将来的应用。

  • abstract
  • async
  • await
  • become
  • box
  • do
  • final
  • macro
  • override
  • priv
  • try
  • typeof
  • unsized
  • virtual
  • yield

变量

在Rust中变量默认不可变(immutale),当变量不可变之后一单值绑定到一个名称上,就无法使用赋值语句来修改,只能使用关键字mut来,把不可变变量变成可变变量,使用大型数据结构时,适当地使用可变变量,可能比复制和返回新分配的实例更快。对于较小的数据结构,总是创建新实例,采用更偏向函数式的编程风格,可能会使代码更易理解,为可读性而牺牲性能或许是值得的。同时也可以使用let来定义一个同名变量把第一个变量覆盖。

标量类型

scalar类型代表一个单独的值。Rust 有四种基本的标量类型:整型、浮点型、布尔类型和字符类型

整型

长度有符号无符号
8-biti8u8
16-biti16u16
32-biti32u32
64-biti64u64
128-biti128u128
archisizeusize

浮点型

f32f64,分别占 32 位和 64 位。默认类型是 f64

布尔型

boolgolang一样

字符类型

chargolang一样

复合类型

Rust 有两个原生的复合类型:元组(tuple)和数组(array),元组不要求每个元素的数据类型一致。Rust的数组和Java的数组一样,长度是固定的。
默认的formater无法直接打印元组 使用println!("this tuple is {:?}",tup) 来打印元组;访问元组内的数据,使用.来按照下标序号处理从0开始。例如tup.0代表输出元组tup的第一个元素。

函数

Rust中的函数 关键字是fn,用来声明一个新函数,通过输入 fn 后面跟着函数名和一对圆括号来定义函数。大括号告诉编译器哪里是函数体的开始和结尾。(比go都少2字母!)太省略了,Rust代码中的函数和变量名使用 snake case规范风格。在 snake case 中,所有字母都是小写并使用下划线分隔单词,Rust的参数变量和类型中间增加了: 顺序和Go一致,都是变量在前,类型在后,Java则是类型在前,变量在后;

fn main() {
    print_labeled_measurement(5, 'h');
}

fn print_labeled_measurement(value: i32, unit_label: char) {
    println!("The measurement is: {}{}", value, unit_label);
}

表达式

赋值语句不含有返回值,在Rust中不支持x=y=6这样的写法,在Rust中,大部分的代码都是表达式组成的,表达式是语句的一部分,如 let y=3;3就是一个特殊的表达式 常量赋值表达式,代码语句块也是一个表达式,如

fn main(){
	let y=1;
	let x= {
	    let y=2;
	    y+2
	};
}
//output y=1,x=4

声明一个Rust函数。开局的main函数是无参的,对于有返回值使用箭头来处理返回值(->)不用对返回值命名,只需要指定类型 如

fn five() -> i32{
        5
}

这函数与如下代码相同:

let x = 5;

细心的您,可能会发现five函数体中并没有代表语句结束的分号,那么是应为5就是一个表达式。如果我们对其增加分号,则表明这是一条语句,而语句则是没有返回值的,编译则会报错哟提示error[E0308]: mismatched types

fn five(x :i32) -> i32{
        x+5;
}

cargo run                
   Compiling hello_cargo v0.1.0 (/Users/bytedance/rust_learning/project/hello_cargo)
error[E0308]: mismatched types
  --> src/main.rs:12:20
   |
12 | fn five(x :i32) -> i32{
   |    ----            ^^^ expected `i32`, found `()`
   |    |
   |    implicitly returns `()` as its body has no tail or `return` expression
13 |     x+3;
   |        - help: consider removing this semicolon

For more information about this error, try `rustc --explain E0308`.
error: could not compile `hello_cargo` due to previous error

控制流

Rust 使用if ,else, else if 来进行分支控制处理,使用Loop来处理循环,在嵌套循环中,break 和 continue 应用于此时最内层的循环。你可以选择在一个循环上指定一个 循环标签(loop label),然后将标签与 break 或 continue 一起使用,使这些关键字应用于已标记的循环而不是最内层的循环

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);
}

小憩一下

  1. 第 N 个泰波那契数
    泰波那契序列 Tn 定义如下:

T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2

给你整数 n,请返回第 n 个泰波那契数 Tn 的值。

impl Solution {
    pub fn tribonacci(n: i32) -> i32 {
        match n {
            0|1=>n,
            2=>1,
            _=>{
                let (mut x,mut y,mut z,mut c)=(0,1,1,2);
                 for _i in 3..=n{
                     c=x+y+z;
                     x=y;
                     y=z;
                     z=c
                 }
                 c
            },
        }
    }
}