RUST 编程

安装 RUST

官网:https://www.rust-lang.org/zh-CN/

哔哩哔哩:点此跳转

下载Rust:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
https://www.rust-lang.org/zh-CN/learn/get-started
https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe

指令说明
rustc构建可执行程序
cargo new --lib project_lib创建库
cargo new project_name创建项目
cargo run运行项目
cargo build生成dev模式的二进制可执行文件
cargo build --release生成高性能的可执行二进制文件
cargo check检查错误
cargo show、cargo --list 、 rustup show显示信息
cargo --version打印版本
rustup更新
rustup --help打印帮助

安装 cargo-edit

安装 :cargo install cargo-edit

添加库:cargo add dependency_name

  • 安装指定版本

    • cargo add dependency_name@123
  • 添加开发时用的以来库

    • cargo add --dev dev_dependency_name
  • 添加构建时用的依赖库

    • cargo add --build build_dependency_name

删除库:cargo rm dependency_name

Cargo.toml 结构:

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----          2025/8/6     10:55                src
d-----          2025/8/6     10:56                target
-a----          2025/8/6     10:55              8 .gitignore
-a----          2025/8/6     10:57           3345 Cargo.lock
-a----          2025/8/6     10:57             88 Cargo.toml
-------------------------------------------------------------------------
PS D:\DevCode\rustc\ex01> cargo add rand@0.8
PS D:\DevCode\rustc\ex01> cat .\Cargo.toml
[package]        
name = "ex01"    
version = "0.1.0"
edition = "2024" 

[dependencies]   
rand = "0.8"  

变量与不可变性

  • 使用 let 关键字声明变量
  • Rust 支持类型推导,也可以显示的指定类型:let x:i32 = 5; (默认类型为有符号i32)
  • 变量名 蛇形命名法(Snake Case),枚举类型贺结构体使用帕斯卡命名(Pascal Case),如果变量没有用到,可以使用前置下划线_name ,消除告警
  • 强制类型转换:let a = 5.2; let b = a as i64;
  • 打印变量({}与{:?}需要实现特质,基础类型默认实现)

    • pringtln!("val: {}",val);
    • pringtln!("cal: {val}");

RUST中的变量是默认不可变的,防止错误,数据竞争、并发等(有利于实现并发安全)

可以使用mut修饰为可变性的

影子特性 shadow ,变量名可以重复,但不影响原有的数据(有待深究)...

fn main() {
    let d = 90;
    {
        let d=10;
        println!("inner x :{}",d);
    }
    println!("outer: {d}");
}
-------------------------------------
inner x :10
outer: 90
=====================================
fn main() {
    let d = 90;
    {
        let d=10;
        println!("inner x :{}",d);
    }
    println!("outer: {d}");

    let mut d:&str = "xinux";

    println!("str:{d}");
    d = "hello";
    println!("重新分配:{d}");
}
-------------------------------------
inner x :10
outer: 90
str:xinux
重新分配:hello

数据类型 (标量类型和复合类型)

shadow 与 mut 是不同的。

fn main(){
    let spaces = "    ";
    let spaces = scpaces.len(); //.len 返回整形
    println!("{}",spaces);
}

标量类型和复合类型:

Rust是静态编译语言,在编译时必须知道所有变量的类型

  • 基于使用的值,编译器通常能够推断出她的具体类型。
  • 但如果可能的类型比较多(例如String转为整数的parse方法),就必须添加类型的标注,否则编译会报错(例子)
fn main(){
    let guess:u32 = "43".parse().expect("Not a Num");
}

标量类型(4种)

  • 整数类型:有符号范围:-(2n-1)到(2n-1-1) ,无符号:0-(2n-1),isize 与 usize由位数决定

    • 整数字面值:

      • dec:98_000
      • hex:0xff
      • Octal:0o77
      • binary:0b111_01
      • byte(u8 only):b'A'

      u8 (0-255),编译release时重新环绕

  • 浮点类型:f32|f64 (默认类型)
  • 布尔类型
  • 字符类型:char 占用4个字节,字符类型的字面值使用单引号,是unicode的标量值,可以表示比ASCII多得多的内容:拼音、中日韩文、零长度空白字符、emoji表情等。

U+0000到U+D7FF

复合类型:

  • 元组:tup: = (1,2,'c');

    • 取元素:tup.index
  • 数组: arr = [1,2,3]; 存在栈上,固定数量元素,vector(长度可变)

    • 定义:arr = []

常量const 与 静态变量 static

Const常量

  • 常量在编译时,就得确定下来值与类型,与宏定义类似,但也有稍稍不同,是直接嵌入到底层生成的机器码中,非宏定义是简单的字符出串替换。
  • 常量名与静态变量名尽量(最好!必须!约定!)大写,单词之间使用下划线。
  • 常量的作用域是块级作用域,他们只在他们生命的作用域可见。
fn main() {
    const SECOND_HOUES:usize = 3_600;
    const SECOND_DAY:usize  = SECOND_HOUES * 24;
    println!("OUTPUT:{SECOND_DAY}");
    -------
    OUTPUT:86400
    -------
    {
        const SE = 1;
    }
    println!("SE:{}",SE);
    -------------
    println!("SE:{}",SE);
   |                      ^^ not found in this scope 报错,找不到,因为是块级作用域。
}

Static变量

  • 与const常量不同,它是在运行时才分配的内存。
  • 并不是不可变的,可以使用unsafe(不安全)修改。
  • 静态变量的生命周期为整个程序的运行时间。
static XINUX_STATIC:i32 = 25;
static mut MY_STATIC:i32 = 95;

fn main() {
    const SECOND_HOUES:usize = 3_600;
    const SECOND_DAY:usize  = SECOND_HOUES * 24;
    println!("{SECOND_DAY}");
    {
        const SE:i32 = 1;
    }
    // println!("SE:{}",SE);
    println!("XINUX_STATIC value is {}",XINUX_STATIC);

    //unsafe 这里执行还是报错,TODOLIST
    unsafe {
        MY_STATIC = 500;
        println!("{MY_STATIC}");
    }
    //println!("MY_STATIC:{}",MY_STATIC);//不行,只能在unsafe里处理
}

基础数据类型

Integer types 默认推断为i32 (有符号)

  • i8、i16、i32、i64、i128

Unsigned Integer Types (无符号)

  • u8、u16、u32、u64、u128

Platform-Specific Integer Type(自动、由平台决定)

  • usize
  • isize

Float Types (浮点)

  • f32、f64
  • 尽量用f64,除非你特别清楚边界。

Boolean :true false

Character Types

  • Rust 支持 unicode 字符
  • 表示 char 类型使用单引号!!
use std::mem;
fn main() {
    let a1 = -198;
    let a2 = 0xFF;
    let a3 = 0o11;
    let a4 = 0b11;
    println!("{a1},{a2},{a3},{a4:0o}");
    println!("usize max:{} === u64 max:{}",usize::MAX,u64::MAX);
    println!("isize max:{} ----- isize min:{}",isize::MAX,isize::MIN);
    println!("i32 max:{} ----- i32 min:{}",i32::MAX,i32::MIN);
    println!("u32 max:{} ----- u32 min:{}",u32::MAX,u32::MIN);
    //浮点型,默认推导32位
    let f1 = 54.98897;
    let f2:f32 = 17.4999999;
    println!("Float f1:{:.2}---------f2:{:.2}",f1,f2);
    //占用多少字节
    println!("isize is {} bytes.",std::mem::size_of::<isize>());
    println!("usize is {} bytes.",std::mem::size_of::<usize>());
    println!("i32 is {} bytes.",std::mem::size_of::<i32>());
    println!("i64 is {} bytes.",std::mem::size_of::<i64>());
    println!("u32 is {} bytes.",std::mem::size_of::<u32>());
    println!("u64 is {} bytes.",std::mem::size_of::<u64>());
    println!("u128 is {} bytes.",std::mem::size_of::<u128>());
    //use std::mem;
    println!("i128 max is {} .---- i128 min is {} .---- the weight {} bytes." ,i128::MAX,i128::MIN,size_of::<i128>());
    println!("u128 max is {} .---- u128 min is {} .---- the weight {} bytes." ,u128::MAX,u128::MIN,size_of::<u128>());
    let is_ok = true;
    let no_ok = false;
    println!("is_ok or no_ok = {}",is_ok||no_ok);
    println!("is_ok and no_ok = {}",is_ok && no_ok);
}
-------------------------------
-198,255,9,3
usize max:18446744073709551615 === u64 max:18446744073709551615
isize max:9223372036854775807 ----- isize min:-9223372036854775808
i32 max:2147483647 ----- i32 min:-2147483648
u32 max:4294967295 ----- u32 min:0
Float f1:54.99---------f2:17.50
isize is 8 bytes.
usize is 8 bytes.
i32 is 4 bytes.
i64 is 8 bytes.
u32 is 4 bytes.
u64 is 8 bytes.
u128 is 16 bytes.
i128 max is 170141183460469231731687303715884105727 .---- i128 min is -170141183460469231731687303715884105728 .---- the weight 16 bytes.   
u128 max is 340282366920938463463374607431768211455 .---- u128 min is 0 .---- the weight 16 bytes.
is_ok or no_ok = true
is_ok and no_ok = false

元组与数组

相同点

  1. 元组和数组都是Compound Types ,而Vec和Map都是Collection Types
  2. 元组和数组长度都是固定的
  • Tuples 不同类型的数据类型
  • Arrays 同一类型的数据类型

数组

  • 数组是固定长度的同构集合
  • 创建方式:

    • [a,b,c]
    • [value;size]
  • 获取元素arr[index]
  • 获取长度arr.len()

元组

  • 元组是固定长度的异构集合
  • Empty Tuple()

    • 为函数默认返回值
  • 元组获取元素

    • tup.index
    • 没有len()
fn main() {
    //tuple 元组 可以是不同类型,没有len方法,
    let tup = (1, "A", 3.1415926);
    let tup2: (usize, isize, bool) = (1, -1, false);

    println!("tup :{} {} {:.2}", tup.0, tup.1, tup.2);
    println!("tup2 :{} {} {}", tup2.0, tup2.1, tup2.2);
    println!("取元组值(tup.2) tup.index:{}", tup.2);
    let mut tup3 = ('a', 'b', 'c');
    tup3.1 = 'X';
    println!("tup3 mut可变元组:{} ,所有值{:?}", tup3.1, tup3);
----------------------------------------
    tup :1 A 3.14
    tup2 :1 -1 false
    取元组值(tup.2) tup.index:3.1415926
    tup3 mut可变元组:X ,所有值('a', 'X', 'c')
----------------------------------------
    //数组 需是相同类型的数据
    let arr = [1, 2, 3, 4, 5, 6];
    let arr2: [u32; 5] = [5, 6, 7, 8, 9];
    println!("取arr数组长度 arr.len():{}", arr.len());
    println!("取arr2数组长度 arr2.len():{}", arr2.len());
    println!("取数组元素arr2[0],值应为5:{}", arr2[0]);
    //数组遍历
    for el in arr {
        println!("arr 数组遍历 :{}", el);
    }
    let arr_yufa = [0; 6]; //6个0
    for i in arr_yufa {
        println!("arr_yufa 数组遍历:{}", i);
    }
    let mut arr_yufa_mut = arr_yufa;
    println!("arr_yufa_mut 是从arr_yufa拿的。{:?}",arr_yufa_mut);
    arr_yufa_mut[0] = 2;
    println!("arr_yufa_mut mut之后修改元素又从arr_yufa拿的。{:?}",arr_yufa_mut);
------------------------------------------
取arr数组长度 arr.len():6
取arr2数组长度 arr2.len():5
arr 数组遍历 :1
arr 数组遍历 :2
arr 数组遍历 :3
arr 数组遍历 :4
arr 数组遍历 :5
arr 数组遍历 :6
arr_yufa 数组遍历:0
arr_yufa 数组遍历:0
arr_yufa 数组遍历:0
arr_yufa 数组遍历:0
arr_yufa 数组遍历:0
arr_yufa 数组遍历:0
arr_yufa_mut 是从arr_yufa拿的。[0, 0, 0, 0, 0, 0]
arr_yufa_mut mut之后修改元素又从arr_yufa拿的。[2, 0, 0, 0, 0, 0]
-------------------------
    //思考 Ownership 基础数据类型 执行copy 操作 复杂数据类型 执行move操作。
    println!("思考 Ownership 基础数据类型 执行copy 操作 复杂数据类型 执行move操作。");
    let a= 3;
    let b = a;
    println!("{a}");
    let name = String::from("Xinux");
    let rename = name;
    println!("{name}");
               报错↑ value borrowed here after move
-------------------------------
思考 Ownership 基础数据类型 执行copy 操作 复杂数据类型 执行move操作。
3
}

内存管理模型

Stack 与 Heap

Stack 按值的接收顺序来存储,按相反的顺序将它们移除(后进先出,LIFO)添加数据叫做压入栈
移除数据叫做弹出栈
所有存储在 Stack上的数据必须拥有已知的固定的大小-编译时大小未知的数据或运行时大小可能发生变化的数据必须存放在heap上
Heap 内存组织性差一些:
-当你把数据放入 heap 时,你会请求一定数量的空间
操作系统在 heap 里找到一块足够大的空间,把它标记为在用,并返回一个指针,也就是这个空间的地址
这个过程叫做在 heap 上进行分配,有时仅仅称为“分配

函数传递所有权

struct Person<'a> {
    name: String,
    age: u8,
    color: &'a str,
}

fn main() {
    //String str
    let name = String::from("Value Xinux");
    //字面量转换成String
    let course = "Rust".to_owned();
    //两种转变方法 String::from() / String::new()
    //to_owned()
    //to_string()
    let ner_name = name.replace("ux", "++");
    println!("{} {} {}", name, course, ner_name);

    //字面量可以直接进行编码
    let rust = "\x52\x75\x73\x74"; //ascii 码
    println!("rust is : {}", rust);

    //使用结构体,传string 进去 ,传递str字面量必须标注 <'a> 、:&'a str才能用
    let name = "John".to_string();
    let age: u8 = 25;
    let color = "red";

    let zhangsan = Person {
        name: name,
        age: age,
        color: color,
    };
    println!("{} {} {}", zhangsan.name, zhangsan.age, zhangsan.color);
    // zhangsan.name = "王五".to_string();

    //func 函数 所有权机制
    let str = "xinux";
    let str_string = "Bypass".to_owned();
    fn print(data: &str) {
        print!("{}",data);
    }

    fn print_string(data: &String) {
        print!("{}",data);
    }
    print(&str);
    print(" admin😄");
    // print_string(str); 行不通

    let val_string = "\nvalue string".to_string();
    print_string(&val_string);


}
------------------------
Value Xinux Rust Value Xin++
rust is : Rust
John 25 red
xinux admin😄
value string

函数

不可以将语句赋值另外一个变量!

let x = (let y=6); //期待是一个值,而不是一个语句,注意加上分号就是语句而不是表达式了。

函数的返回值:

  • 在->符号后面生命返回值类型,不可以为返回值命名,但是要指定类型
  • 在Rust中,返回值就是函数体中最后一个表达式的值
  • 若想提前返回,需要使用return 关键字,并指定一个值

    • 大多数函数都是默认使用最后一个表达式作为返回值
  • 注意加上分号就是语句而不是表达式了。

控制流

if else match 重构

fn main() {
    let number = 6;
    if number % 4 == 0 {
        println!("divisible by 4");
    }else if number % 3 == 0 {
        println!("divisible by 3");
    }else if number % 2 == 0 {
        println!("divisible by 2");
    }else{
        println!("divisible is not by 4,3,2");
    }

    //match 重构
    match number {
        n if n % 3 == 0 => println!("divisible by 3"),
        n if n % 2 == 0 => println!("divisible by 2"),
        _ => println!("divisible is not by 4,3,2")
    }

}

循环

loop break

while 执行循环前,都会判断一下条件

for 遍历集合,遍历数组,for element in range(1..5){}

.rev() 反转

结构体 struct

定义和实例化struct

枚举

  • IP地址:IPv4、IPv6

enum IpAddrKind{

​ V4,

​ V6,

}

如何创建枚举值:

let four = IpAddrKind::V4;

let six = IpAddrKind::V6;

版权属于:管理员
本文链接:https://xinux.top/index.php/archives/rust-study.html
本站未注明转载的文章均为原创,并采用 CC BY-NC-SA 4.0 授权协议,转载请注明来源,谢谢!