ITPub博客

首页 > 数据库 > 数据库开发技术 > 5分钟入门Rust基础

5分钟入门Rust基础

原创 数据库开发技术 作者:Rust嵌入式 时间:2024-01-17 19:42:49 0 删除 编辑

前言

2022,越来越多的公司开始用Rust来重构项目了,如微软重构windows内核,rust成为Linux内核驱动的最佳支持语言,马斯克的X公司也用Rust重构人工智能,Boss的招聘条件开始加上会Rust优先,越来越多的爱码仕们也在悄咪咪地练习borrow checker,某天要是看见同事对着屏幕发飙:什么玩意儿,不倒腾了!,没错!也许他正在学习Rust的路上。

如何打印打印

Rust 入门从打印开始,通常可使用println! 宏在标准 IO 输出显示。使用非常简单,只可在占位符{}的位置输出对应的变量的值。

fn main() {
    // Hello, world!
    println!("Hello, world!");
    println!("number: {} string: {}", 1, "hello");
}

基本数据类型

Rust 的基本类型与 C/C++非常相似,但命名变量类型名更加精确,非常容易知晓变量所占的内存空间大小。基本类型有:

  • i8, i16, i32, i64, i128, f32, f64, bool
  • u8, u16, u32, u64, u128

fn main() {
    // 定义一个 u8 类型
    let val: u8 = 0xff;
    // 定义一个 u16 类型, 在一个代码范围内相同相同名字的变量,实际上不是上一个变量了,
    let val: u16 = 0x1234;
    // 定义一个 u32 类型, `_`符号认为该变量可能不会使用,因此编译时不报警
    let _val8: u32 = 0x12345648;
    // 定义一个 u64 类型
    let _val: u64 = 0x1234567812345678;
    // 定义一个 u128 类型
    let _val: u128 = 0x12345678123456781234567812345678;
    // 定义一个 i8 类型, 类型会自动推导出
    let _val = 127 as i8;
    // 定义一个 i32 类型,类型会自动推导出
    let _val = 250i32;
    // 定义一个 i64 类型,类型会自动推导出
    let _val = 123456_i64;
    // 定义一个 i64 类型,类型会自动推导出
    let _val = 1000_000_000 as i64;
    // 定义一个 i128 类型, 类型会自动推导出
    let _val = 1000_000_100_111 as i128;
    // 定义一个 f64 类型,类型会自动推导出,浮点数默认为 f64类型
    let _val = 1.001_33;
    // 定义一个 f32 类型,类型会自动推导出
    let _val = 1.010_33 as f32;
    // 定义一个字符串切片
    let _num = "123";
    // 将字符串切片解析为 i32 类型
    let _num: i32 = _num.parse().unwrap();

    // 定义一个字符串
    let _num = String::from("456.6");
    // 将字符串解析为 f32 类型
    let _num = _num.parse::<f32>().unwrap();

    // 为 u32 类型重新定义一个别名
    type U32 = u32;
    let _val: U32 = 0x1234;
    let _val = 0x1234 as U32;

    // 定义一个 f32 的浮点数
    let _vf32: f32 = 3.14;
    // 浮点数默认为 f64 类型
    let _vf64 = 3.14;
}

结构体、枚举、元组

Rust的 结构体和枚举非常灵活,struct内部的属性能指定为任意类型,如普通的基本类型,枚举等,甚至零大小类型。enum也非常灵活,在C/C++的基础上,增加类型附带的值,能非常直接得描述对象的逻辑,提供了抽象能力,然而并不会带来内存或效率的损耗。元组类型通常用在一些对属性名不重要的场合,类似Python中元组的概念。参考以下代码了解Rust的struct和enum和元组的特点。

use std::mem::size_of;
use std::mem::size_of_val;

// 定义一个 Man 的结构体,包含两个变量
mod people{
    use crate::Gender;

    // 定义一个 Man 的结构体,指定为 pub 属性
    pub struct Man{
        // 定义 age 属性,指定为私有属性,模块外不能访问
        age: u32,
        // 定义 name 属性,指定为 pub 属性,模块外能直接访问
        pub name: String,
        // 定义 gender 属性,指定为 pub
        pub gender: Gender,
    }

    // 构造一个 pub 函数, 使用该函数生成 Man 对象
    pub fn new_man(age: u32, name: &str, gender: Gender) -> Man{
        Man{
            age: age,
            name: name.to_string(),
            gender: gender
        }
    }
}

// 定义一个 Mode 的结构体,内部 mode 的属性为模板 T 指定
struct Mode<T>{
    mode: T,
}

// 定义一个 Water 的结构体,大小为0
struct Water;

// 定义 Gender 枚举,有三个属性
enum Gender {
    Man,
    Femel,
    Others,
}

#[derive(Debug)]
enum Color{
    Red = 0xff0000,
    Green = 0x00ff00,
    Others
}

// 定义一个 Pregnant 的枚举,只有一个属性,属性中附带一个 i8 的变量,
// 表示 Baby 的数量
enum Pregnant{
    Baby(i8),
}

// 定义一个 Fruit 的枚举, 内部包含的属性,附带 T 类型的数据
enum Fruit<T>{
    Apple(T),
    Grape(T)
}

struct Tuple(i8, i32, String, Color);

fn main() {
    let man = people::new_man(20, "hunter", Gender::Man);
    println!("man's name: {}", man.name);
    // age 是私有变量,不能在模块外面访问
    // println!("man's age: {}", man.age);

    let mode:Mode<bool> = Mode { mode: true };
    println!("mode: {}", mode.mode);

    // 构造一个 water 的变量,并打印变量的大小
    let water = Water;
    println!("Water size: {}", size_of_val::<Water>(&water));
    println!("Water size: {}", size_of::<Water>());

    // 构造一个 Gender 的枚举变量,并初始化值
    let gender = Gender::Man;
    println!("gender size: {}", size_of_val::<Gender>(&gender));

    // 构造一个 Color 的枚举变量,并初始化值
    let color = Color::Red;
    println!("Color size: {}", size_of_val::<Color>(&color));

    // 构造一个 Pregnant 的枚举,并初始化值
    let baby = Pregnant::Baby(2);
    let Pregnant::Baby(number) = baby;
    println!("Enum Pregnant size: {}", size_of_val::<Pregnant>(&baby));
    println!("baby: {}", number);

    // 构造一个 Fruit 的枚举值,并初始化值
    let apple: Fruit<Color> = Fruit::Apple(Color::Red);
    // 根据 内部值的类型打印细节
    match apple {
        Fruit::Apple(c) => println!("Apple color: {:?}", c),
        Fruit::Grape(c) => println!("Grape color: {:?}", c),
    }

    // 构造一个 元组,并打印
    let tuple = Tuple(127, -1, "Tuple String".to_string(), Color::Red);
    println!("tuple: {} {} {} {:?}", tuple.0, tuple.1, tuple.2, tuple.3);

}

在Rust的枚举中,非常重要的默认枚举类型如Option<T>,Result<T,E>等也经常使用在日常开发中。

判断

Rust的条件判断语句有if、if-else、if-else if-else、match、if let 等语句,与C/C++最大的不同是,这些语句都能像函数一样返回数据。参考如下实例简单理解。

fn main() {
    let result = true;

    // if 后面无需增加括号(),但必须添加代码块符号{}
    if result {
        println!("Result is true");
    }
    else {
        println!("Result is false")
    }

    let number = 4;
    if number == 4{
        println!("number == 4");
    }

    let count = 10;
    // if 判断里面只能为 bool 类型,不会针对数字隐式转换
    // if count {  // count 是 i32 类型, 不是 bool 类型,所以会编译报错
    if count > 0 {
        println!("count > 0");
    }

    // if 语句可以返回数值,类似 C/C++ 的三元操作: bool r = true? false: true;
    let _r = if result ==  true {
        false
    }
    else {
        true
    };

    // match 类似 C/C++ 的switch 语句,但是match 要求必须完全枚举所以得可能,否则编译报错
    // match 匹配也可以返回一个值,可以使用也可以省略返回的
    let r = match count {
        // 匹配转向符为 =>  末尾添加,
        10 => println!("count is 10"),
        // 必须匹配剩余的可能性
        _v => println!("count is {}", _v),
    };

    let r: Option<i32> = Some(1);
    // if let 语句,根据匹配结果取出内部的数据
    if let Some(v) = r {
        println!("Some: {}", v)
    }
}

循坏

Rust的循坏语句也非常丰富,常用的有loop``while``for,特殊一点的有wile let,非常实用,参考如下代码简单了解特性


fn main() {
    let arr: [i32; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

    for v in arr {
        println!("{}", v);
    }

    let mut max = i32::MAX;
    for i in 0..arr.len() {
        if max < arr[i] {
            max = arr[i];
        }
    };

    let mut idx = 0;
    let len = loop {
        if idx < arr.len(){
            println!("{}", arr[idx]);
            idx = idx + 1
        }
        else {
            break idx
        }
    };

    let mut idx = 0;
    while idx < arr.len() {
        println!("{}", arr[idx]);
        idx += 1;
    }

    let mut s = Some(1);
    // 当 s 为some时候能进入循坏,否则不进入循坏
    while let Some(i) = s {
        println!("once");
        s = None;
    }
}

函数

Rust的函数定义与C/C++稍许不同,Rust对函数定义和调用的顺序不做要求,也无需预定义,使用关键字fn表示为函数定义,返回使用->指定,函数内部的返回使用return关键字或最后执行的语句所带的值作为返回值。同时像C++一样支持函数模板,但更加简单易用。参考如下代码了解函数定义的特性。


fn test(num: i32) -> i32 {
    println!("val: {}", num);
    num
}

fn max(v1: i32, v2: i32) -> i32 {
    if v1 > v2 {
        v1
    }
    else if (v1 == v2) {
        return v1
    }
    else {
        v2
    }
}
// 定义简单的重载函数,生成同不的类型的参数的函数
fn fun<T>(t: T) {
}

// ! 表示该函数永远也不会返回
fn infinite() ->!{
    loop {

    }
}

fn main() {
    let _t1 = test(1);
    let _max = max(1, 2);
    fun::<i32>(1);
    fun::<&str>("1");
    infinite()
}


原文作者:Rust嵌入式;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2023-11-13

  • 博文量
    64
  • 访问量
    45582