Rust入门(二):基础语法

Rust变量

rust中使用let关键字来初始化一个变量,变量在初始化的时候必须有一个初始值,同时rust中变量不可变,在初始化之后就不可以再更改了:

//变量不可变
let x = 5;
//这种情况是不允许的,不可以二次赋值
x = 6;

使用mut关键字可以使得变量成为可以改变的:

//变量不可变
let mut x = 5;
//这种情况是允许的,mut变量二次赋值
x = 6;

使用const关键字可以定义常量,常量不可以mut,并且必须声明类型,可以在全局定义,全大写。常量可以在任何作用域中声明,比如main函数之前:

const X:i32 = 1000;

如果我们先声明一个变量,之后再用let声明同一个变量,这是允许的,我们称之为第一个变量隐藏了,这一个过程中,变量的类型和数值都可以改变,这一个操作的好处是节约内存:

//shadow
let x = 5;
let x = true;

Rust基础数据类型

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

  • 整数

rust的整数分为有符号和无符号两种,同时我们可以通过设定长度来限制整数的长度,长度可以设置为8,16,32,64,128这几种,同时rust还支持使用isize这样的形式定义整数,它可以根据本机的位数来设定长度,比如64位的电脑就与i64的效果一致。可以使用下面两种方式来定义一个指定类型的整数

let num:u8 = 42;
let num = 42u8;

同时我们可以使用多种进制来表述一个整数类型值

//十进制,可以使用_隔开,与98222一致
let num = 98_222;
//十六进制
let num = 0xff;
//八进制
let num = 0o77;
//二进制
let num = 0b1111;
//单字节字符(仅限u8)
let num = b'A';
  • 浮点数

​浮点数仅有32和64位两种类型,默认类型是 64位浮点数

//这个时候就算f64
let x = 2.0;
let y:f32 = 2.0;

Rust 中的所有数字类型都支持基本数学运算:加法、减法、乘法、除法和取余,分别使用 +,-,*,/,%符号来完成,除法会向下取最接近的整数。

  • 布尔型

​Rust 中的布尔类型(bool)有两个可能的值:true和 false

//boolean
let t:bool = true;
  • 字符类型

​rust中的字符类型数据占4给字节,并且使用 Unicode 编码,所以我们可以使用英文字母,外文字母,emjoy表情等字符:

let c = 'z';
let z: char = 'ℤ'; 
let heart_eyed_cat = '😻';

Rust复合数据类型

复合类型将多个值组合成一个类型,Rust 有两个原生的复合类型:元组(tuple)和数组(array)

  • 元组

​元组tuple,长度固定,且内容不能修改,元组中的数据类型可以不同

let tup = (10,21,'c');

使用模板匹配的方式可以提取出元组的每一个数据,也可以通过下标来访问

let (x,y,z) = tup;
let k = tup.1;

不带任何值的元组有个特殊的名称,叫做单元(unit) 元组。这种值以及对应的类型都写作 (),表示空值或空的返回类型。如果表达式不返回任何其他值,则会隐式返回单元值。

  • 数组

​数组array同样长度固定,但是其中的类型必须一致,内容也同样不可变:

let arr = [1,2,3,4];
//使用[类型;数量]的方式可以定义数组的类型
//同时如下方式可以直接生成[3,3,3,3,3]5个3的数组
let a:[i32;5]= [3;5];

数组可以通过下标访问

let first = a[0];

Rust的函数

fn关键字,它用来声明新函数,函数中的参数必须声明类型,如果函数有返回值,返回的内容也必须给出类型,函数的定义如下:

//函数定义,参数类型必须指明,返回值也需要声明
fn test(x:i32,y:i32)  -> i32 {
    5
}

函数中的执行某些操作的指令被称为语句,语句由分号结尾;二返回一个值的指令被曾为表达式,表达式不能由分号结尾,一个函数可以包括多个语句,同时在函数结尾需要一个表达式来作为函数的返回值。

//函数定义,参数类型必须指明,返回值也需要声明
fn test(x:i32,y:i32)  -> i32 {
    //语句
   	let x = x+1;
    let y = y+1;
    //表达式
    x+y
}

Rust控制流

rust和其他语言类似具有if等条件控制语句,也有while和for等循环语句

  • if

​if 表达式允许根据条件执行不同的代码分支。if 语句中包含一个表达式,表达式的值必须是一个bool类型,返回true或者false,要注意,rust并不会将其他类型的值转化为bool进行运算,if(1)这些的写法是不允许的:

if number > 5 {
    println!("1");
}else if number == 5 {
    println!("2");
}else{
    println!("3");
}
//这样是不允许的:
if number {
}

可以通过在 if 语句中返回一个表达式来实现“三目运算” 等类似操作,但是返回值必须是同一个类型

let condition = true;
//相当于三目运算,但是返回值必须一致
let num = if condition {5} else {6};
  • loop循环

​loop 循环将循环执行它包含的语句,直到遇到 break 关键字将其中断,同时在break之后还可以编写一个表达式作为返回值。要注意,此处需要一个分号,因为整个语句是一个赋值语句。

let mut conuter = 1;
let re = loop {
     conuter += 1;
     if conuter == 10 {
         //返回,并且可以返回值
         break conuter * 2;
     }
};
//整个相当于一个 let re = 10 * 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循环

​while 循环在指定的条件为真时循环执行

while conuter != 0 {
      conuter = conuter -1;
}
  • for循环

​for 循环可以限定循环的次数,你可以用 for 语句遍历一个数组中的每一个元素,也可以使用range自己创建一个循环的范围来限定循环次数,使用range创建的范围是 [ a,b ) 的区间,可以取到初值但是不能取到末值

let a = [10, 20, 30, 40, 50];
for e in a {
   println!("{}",e);
}
//在一个范围内运行,不包含10,包含1
for e in (1..10) {
   println!("{}",e);
}

Rust结构体

rust使用struct来定义一个包含多种数据类型的结构,struct 中的每个字段需要给出名字和数据类型,在创建一个struct 实例时,需要对其中的每一个字段赋值,同样,struct 实例也可以是可变的,如果一个 struct 实例是可变的,那么其中的每一个字段都是可变的,使用 . 记号可以找到实例中的字段

struct User {
     name:String,
     email:String,
     active:u32,
}
//实例化
let mut user1 = User{
     email:String::from("122"),
     name:String::from("zs"),
     active:1,
};
//修改一个值
user1.email = String::from("121212");
//如果给与一个字段的值和他的名称一致,可以省略不写,如下:
let email = String::from("122");
let mut user2 = User{
     email,
     name:String::from("zs"),
     active:1,
};

使用扩展运算符 .. 可以将一个struct 实例展开,展开的 struct 可以用于填出其他的 struct 实例

let mut user2 = User{
    ..user1
};

rust 还支持元组 struct 这样的 struct ,他的定义类似于元组,字段不需要名称,字段的获取方式也和元组类似

//tuple struct,变量没名字
struct Color(i32,i32,i32);
let black = Color(0,0,0);

使用 impl 块可以为 struct 创建方法,需要传入一个 &self 代表本身,传入这个参数之后,可以调用 struct 中的字段元素,在 self 之后可以传入其他元素,将 struct 实例化之后,使用 . 来调用对应的方法,要注意,调用方法时,并不需要传入 &self 这个参数

struct Long{
    a:u32,
    b:u32,
};
//impl块用于定义方法
impl Long {
    fn greater(&self, other: &Long) -> u32 {
        if self.a > other.a {
                1
        }else{
                2
        }
    }
};
println!("{}",l1.greater(&l2))

如果函数中不包含 &self 这个参数,那么这个函数不需要实例化也可以调用,调用方式也是使用 :: 来调用,类似我们之前使用的在String中的 String::from ,这类函数常用于初始化一个 struct 实例,类似于其他语言中的 new

impl Long {
    fn creat_long(a: u32) -> Self {
        Self {
            a: a,
            b: a,
        }
    }
}
let l3 = Long:: creat_long (1);

Rust枚举

枚举类型允许你给出所有的可能值作为成员创建一种新的数据类型,使用 :: 可以创建一个枚举中一种类型的实例。当你使用 IpAddrKind 作为变量类型时,IpAddrKind::V4 和IpAddrKind::V6 都可以与其匹配

enum IpAddrKind {
    V4,
    V6,
}
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;
//route(IpAddrKind::V4) 和 route(IpAddrKind::V6) 都可以传入
fn route(ip_kind: IpAddrKind) {}

在rust中,我们可以直接将数据附加到枚举的每个成员上,这里直接展示一个例子来说明:

enum IpAddr {
   V4(u8, u8, u8, u8),
   V6(String),
}
let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));
//这种方式相当于,loopback的类型是IpAddr::V6,同时home的值是"::1"

可以使用 impl 来为结构体定义方法那样,也可以在枚举上定义方法,其使用方式与 struct 类似

impl IpAddr {
     fn call(&self) {
         // 在这里定义方法体
     }
}
let loopback = IpAddr::V6(String::from("::1"));
loopback.call();

Rust空值

rust 并没有很多其他语言中有的空值功能,空值的问题在于当你尝试像一个非空值那样使用一个空值,会出现某种形式的错误。但是rust是一门追求安全的语言,所以rust 并没有空值,但是提供了一个 Option<T> 枚举,他包含两个值,一个是 None 代表空,一个是 Some ,代表非空

enum Option<T> {
    None,
    Some(T),
}

let some_thing = Some(5);
let absent_number : Option<i32> = None;

因为rust需要确保安全,所以 Option 和 T 不能直接进行运算

let x: i8 = 5;
let y: Option<i8> = Some(5);
//这是不允许的,即使y不是None
let sum = x + y;

match 控制流

match 控制符允许我们将一个值与一系列的模式相比较,并根据相匹配的模式执行相应代码,例如使用一个枚举类型,我们可以根据输入值是枚举的哪一项执行不同的操作,match的每一项返回值必须是同一个类型,如果仅返回一个值,不需要大括号进行包裹,但是如果你需要执行多个语句,则需要一个大括号进行包裹

enum Coin{
    Penny,
    Nickel,
    Dime,
    Quarter(i32),
}

fn in_cents(coin:Coin) -> u8 {
    match coin {
        Coin::Penny => {
            println!("111");
            1
        },
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter(state) => {
            println!("{}",state);
            25
        },
    }
}

当然如果你仅需要匹配其中的部分内容,你可以使用占位符 _ 代表其他剩余的元素

fn in_cents(coin:Coin) -> u8 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        _ => 2,
    }
}

如果的只需要匹配其中一个元素,你还可以使用 if let 语法糖来优化,下面两种表达的效果相同

match coin {
    Coin::Quarter(state) => println!("State quarter from {:?}!", state),
    _ => count += 1,
}
//和上面表述相同
if let Coin::Quarter(state) = coin {
    println!("State quarter from {:?}!", state);
} else {
    count += 1;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

摸鱼老萌新

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值