前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Rust修仙笔记之筑基期

Rust修仙笔记之筑基期

作者头像
Maic
发布2024-02-29 16:52:24
890
发布2024-02-29 16:52:24
举报
文章被收录于专栏:Web技术学苑
在上一节中我们了解了rust最基础的使用,如何使用宏打印,用了一个最简单的猜数游戏了解了rust中的基本用法,今天我们还是从rust中的基础知识中去学习rust,本文主要参考学习文档rust[1]

变量不可变性

当我用let声明一个name变量时,这个变量是不可变的

代码语言:javascript
复制
 
fn main() {
    let name = "Maic";
    println!("Hello, {}!", name);
}

当我们重新对name进行覆值时会报错

代码语言:javascript
复制
 
fn main() {
    let name = "Maic";
    name = "2";
    println!("Hello, {}!", name);
}

/**
2 |     let name = "Maic";
  |   ------ expected due to this value
3 |     name = '2';
  |            ^^^ expected `&str`, found `char`
**/

变量的可变性

如果我想让一个申明的变量可变,只需用mut修饰即可,注意我们右侧的变量用双引号,不能用单引号。

代码语言:javascript
复制
 
fn main() {
    let mut name = "Tom";
    println!("Hello, {}!", name);
    name = "Jake";
    // name = 'jake' error
    println!("Hello, {}!", name);
}
/*
  打印的结果是:
  Hello, Tom!
  Hello, Jake!
*/

常量

我是使用const申明变量,且变量名是大驼峰命名,且申明这个变量,我们使用u32类型

代码语言:javascript
复制
 
fn main() {
    const NAME_RESULT: u32 = 60 * 60;
    println!("Hello, {}!", NAME_RESULT);
}

遮蔽变量

我们使用let变量重复定义同一个变量名,这样会导致,第二个变量是前一个变量的引用

代码语言:javascript
复制
 
fn main(){
   // 1
   let x:i32 = 5;
   // 2
   let x:i32 = x + 1;
   {
     // 3
     let x:i32 = x + 3;
     println!("hello x1={}",x);
   }
   // 4
   println!("hello x2={}", x)
}

我们会发现我们重复申明了x3次,打印的结果是x1=9 x2=6。在第2行申明的x,引用的就是1处申明的变量,在第3行使用的是第二2行申明的变量,{}可以申明成一个独立的块作用域,而4引用就是2处申明的变量。

从结果上来看,21遮蔽了,32遮蔽了,但是4引用的是2处的变量

遮蔽变量类型不可变

在以上我们重复用let定义了不可变量,我们发现遮蔽变量不可重新赋值且类型不可变

代码语言:javascript
复制
 
fn main() {
  let y:u32 = 5;
  y = 10; // cannot mutate immutable variable `y`
  println!("hello, {}", y)
}

要解决这个问题,我们只需把y变成mut即可,将该变量申明成一个可变量

代码语言:javascript
复制
 
fn main() {
  let mut y:u32 = 5;
  y = 10;
  println!("hello, {}", y)
}

那什么类型不可变,比如说:

代码语言:javascript
复制
 
fn main() {
    let str_name = "hello";
    str_name = str_name.len(); // error expected `&str`, found `usize`
    println!("hello, {}", str_name);    
}

我们用let申明了一个不可变变量,然后又重新赋值,并且获取了字符串的长度

此时打印str_name编辑就提示报错了

当我们使用不可变量想能重新赋值时,类型不可强制转换

代码语言:javascript
复制
 
// ok
fn main() {
   let str_name = "hello";
   let str_name = str_name.len();
   println!("hello length, {}", str_name); // 5
}

// error
fn main() {
    let mut str_name = "hello";
    str_name = str_name.len(); // 获取字符串的长度,
    println!("hello length, {}", str_name);
}

综上,我们会发现,在同一作用域内,当我们使用let申明同一个变量时,会存在变量遮蔽,不同作用域,会使用最近申明的遮蔽变量

注意在rust中我们声明的变量是小驼峰命名。当我们使用的一个mut申明的变量,再没有使用时候,会警告

代码语言:javascript
复制
 
fn main() {
    let mut y: u32 = 5;
    y = 10;
    println!("hello2, {}", y);
}

数据类型

rust中主要有以下两大类类型标量类型复合类型

其中标量类型主要有四种:整型浮点型布尔型字符

复合类型主要有元组类型数组类型

在以上我们使用let定义了一个不可变的变量,在rust中在编译期就知道其变量类型。

如果我想把字符串类型转换成数字类型,那如何做到呢?

代码语言:javascript
复制
 
fn main() {
    let guess_number = "12";
    let guess_number: u32 = guess_number.parse().expect("not a number");
    println!("guess number, {}", guess_number);
}

我们通过调用guess_number.parse()方法将字符串转换成了数字类型。

整型类型里主要有两大类,有符号(i)类型、无符号(u),在有符号(i)类型主要有i8(-128~127),i16,i32,i64,i128,在无符号(u)上类型主要有u8(0-255),u16(0-2^16-1),u32(2^32-1),u64,u128

  • 整型
代码语言:javascript
复制
 
// 有符号类型
let x:i8 = 10;
println!('{}',x);
// 无符号类型
let y:u8 = 20;
println!('{}',y);
  • 浮点型
代码语言:javascript
复制
 
let float_number:f32 = 2.5;
println!("float_number,{}", float_number);
  • 布尔类型
代码语言:javascript
复制
 
let is_true:bool = true;
println!('float_number,{}', is_true);
  • 字符串型
代码语言:javascript
复制
 
let a_num:&str = 'hello'

复合类型

rust中复合类型主要包含以下两种,一是元组(多种类型组合在一起形成一种复合类型,也就是元组),二是数组(同一种数据类型组合在一起,且有长度)

  • 元组类型

定义的类型一一对应,主要有(i32,f64,u8)三种类型

代码语言:javascript
复制
 
fn main() {
  let tuple_number: (i32,f64, u8) = (800,1.2,5);
  println!('tuple_number-0', tuple_number.0);
  println!('tuple_number-1', tuple_number.1);
  println!('tuple_number-2', tuple_number.2);
}

对元组进行解构

代码语言:javascript
复制
 
let (x,y,z) = tuple_number;
  • 数组 可以有以下几种方式
代码语言:javascript
复制
 
let name_array:[i32;5] = [1,2,3,4,5];

let name_array = ['a';5];
// 以上等价于
let name_array = ['a','a', 'a', 'a', 'a']

如何获取一个数组栈内存分配的大小

mem::size_of_val(&DATA_NUMBER)获取栈内存的大小

代码语言:javascript
复制
 
use std::mem;

fn main() {
    // 申明数组的长度
    const DATA_NUMBER: [i32; 5] = [1, 2, 3, 4, 5];
    println!("data is length {}", DATA_NUMBER.len());
    // data在内存中
    println!("data is {:?}", mem::size_of_val(&DATA_NUMBER));
}

自定义类型

rust中可以自定义类型,主要自定义类型方式有两种,一是结构体,二是枚举方式

#[derive(Debug)]

代码语言:javascript
复制
 
#[derive(Debug)]
struct Person {
    name: String,
    age: i8,
}
fn main() {
  let name = String::from("Maic");
  let age = 18;
  let user_info = Person {name, age};
  println!("user.name:{},user.age:{}", user_info.name, user_info.age);
  // 解构
  let Person{name, age} = user_info;
  println!("{},{}",name, age);
}
  • 解构元组
代码语言:javascript
复制
 
// 带有两个字段的解构体
struct Point {
   x:f32,
   y:f32
}

struct Pair(i32,f32);

fn main() {
  let x = 1.1;
  let y = 1.2;
  let point:Point = Point {x,y};
  println!("x={},y={}",point.x,point.y);
  let pair = Pair(1.1,3.4);
  let Pair(x,y) = pair;
  println!("x={},y={}", x,y);
}

枚举

我们使用enum关键词定义了WebEvent,在这个枚举中我们看到有 PageLoadPageUnloadKeyPress(char)Paste(String)Click {x: i64, y:i64}

代码语言:javascript
复制
 
// 主要用于隐藏对未使用代码的警告
#![allow(dead_code)]

enum WebEvent {
   PageLoad,
   PageUnload,
   KeyPress(char), // 元组结构体
   Paste(String),
   Click { x: i64, y: i64 },
}

// 将枚举WebEvent当成inspect的形参
fn inspect(event: WebEvent) {
    match event {
        WebEvent::PageLoad => println!("page loaded"),
        WebEvent::PageUnload => println!("page unload"),
        WebEvent::KeyPress(c) => println!("keypress:{}", c),
        WebEvent::Paste(s) => println!("Paste,{}", s),
        WebEvent::Click { x, y } => {
            println!("x={},y={}", x, y)
        }
    }
}
fn main() {
    let pressed = WebEvent::KeyPress('x');
    let pasted = WebEvent::Paste("my name".to_owned());
    let click = WebEvent::Click { x: 20, y: 80 };
    let load = WebEvent::PageLoad;
    let unload = WebEvent::PageUnload;
    let x = OtherVeryVerBoseEnum::Add;
    inspect(pressed);
    inspect(pasted);
    inspect(click);
    inspect(load);
    inspect(unload);
    println!("Hello, world!");
}

use

当我们使用enum申明了一个枚举时,在main方法中可以使用use关键词引入Work

代码语言:javascript
复制
 
#![allow(dead_code)]

enum Work {
  Civilian,
  Soldier
}

fn main () {
   use Work::*;
   // 与下面等价
   /*
     use Work::{Civilian, Soldier}
   */
   let work_civilian = Civilian;
   match work_civilian {
     Civilian => println!("the civilian"),
     Soldier => println!("soldiers fight")
   }
}

if

if条件语句,当我们使用if条件时,可以将判断后的语句进行赋值操作

代码语言:javascript
复制
 
fn main() {
    let number = 10;
    // 注意if后面并没有括号
    let new_number = if number < 0 {
        println!("to small");
        -10 // 注意这里没有分号,会赋值给表达式new_number
    } else {
        println!("to big");
        100 // 这里也会赋值表达式new_number
    };
    println!("{}", new_number);
}

for循环

循环一个范围数据,比如[a,b]之间

代码语言:javascript
复制
 
fn main() {
    // for循环a..=b 表示[a,b]范围
    for item in 1..=10 {
        println!("item1: {}", item);
    }
    // a..b 表示[a,b)范围
    for item in (1..11).rev() {
        println!("item,{}", item);
    }
    // vec!申明一个可迭代器的变量
    let names = vec!["a", "b", "c"];
    for item in names.iter() {
        match *item {
            "a" => println!("There is a rustacean among us!"),
            _ => println!("Hello {}", item),
        }
    }
}

可以修改循环中的数组,使用names3.iter_mut()

代码语言:javascript
复制
 
 let mut names3 = vec!["Bob", "Frank", "Ferris"];
    for name in names3.iter_mut() {
        *name = match name {
            &mut "Ferris" => "hello",
            _ => "a",
        }
    }
    println!("names3:{:?}", names3);
    // names3:["a", "a", "hello"]

match

匹配对应条件,并返回,当我们使用match时,如果条件不满足会默认走_ => println!("other case!"),如果满足其中任意条件,则会走其中任意一分支,如果match返回一个值,则会走match匹配的分支

代码语言:javascript
复制
 
fn main() {
    let number = 2;
    println!("number is {}", number);
    match number {
        1 => println!("first one"),
        2 | 3 => println!("{}", number),
        5..=6 => println!("good luck"),
        _ => println!("other case!"),
    };

    let boolean = false;
    let binary = match boolean {
        false => "false",
        true => "true",
    };
    println!("{} -> {}", boolean, binary);
}

enum

代码语言:javascript
复制
 
// 消除警告,使用枚举类型取值
#[allow(dead_code)]
// 加了这个不会报错,第15【Color::Red => println!("color is red,{:?}", color)】行不会报错
#[derive(Debug)]
enum Color {
    Red,
    Blue,
}

fn main() {
    // &表示取引用
    let reference = &4;
    let color = Color::Red;
    match color {
        Color::Red => println!("color is red,{:?}", color),
        Color::Blue => println!("color is blue"),
    }
    match reference {
        // &val指向的是reference
        &val => println!("value is {}", val),
    }
    // 等价于上面,使用*引用,这样val不用加&
    match *reference {
        val => println!("value2 is {}", val),
    }
    // 没有引用
    let no_reference = 3;
    match no_reference {
        val => println!("value3 is {}", val),
    }
    match no_reference {
        ref val => println!("value4 is {}", val),
    }
    let mut value = 10;

    match value {
        ref mut val => {
            // 先用*解引用,然后+10
            *val += 10;
            println!("value5 is {}", val);
        }
    }
}

总结

  • 我们学习到了rust中的可变变量与不可变量,通常来讲使用let申明的变量是不可变的,而且在rust中可以重复定义同一变量名,但此时会发生遮蔽变量。
  • 我们学习了rust中最基本的数据类型,主要分两大类,标量类型复合类型,其中标量类型主要包含,整型浮点型布尔型字符串型,复合类型主要包括,元组类型数组类型
  • 了解到use,if,match,forenum的使用
  • 本文示例代码code example[2]

参考资料

[1]rust: https://rustwiki.org

[2]code example: https://github.com/maicFir/rustLesson

最后,看完觉得有收获的,点个赞,在看,转发,收藏等于学会,原创不易,欢迎关注Web技术学苑,好好学习,天天向上!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-02-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Web技术学苑 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 变量不可变性
  • 变量的可变性
  • 常量
  • 遮蔽变量
  • 遮蔽变量类型不可变
  • 数据类型
  • 复合类型
  • 自定义类型
  • 枚举
  • use
  • if
  • for循环
  • match
  • enum
  • 总结
  • 参考资料
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档