05-变量与可变性

前言

前几篇文章中,我们已经对 Rust 有了一个初步的了解,并通过一个 猜数游戏 的小程序的开发,抢先接触了 Rust 的一些语法特性,但大多都是浅尝辄止,未曾深入,从这个章节开始,我们就来一步步地深入学习这些语法特性,力求将这些语法特性都吃透,并能够灵活应用。

接触程序,我们首先需要接触变量,所以,我们今天这篇文章就以变量与可变性 作为切入点正式进入 Rust 的语法世界。

let

我们在前几章已经反复讲了好多次 let 相关的内容了,这边就不再赘述了,总得来说就是:

使用 let 可以定一个不可变的变量,如果想要这个变量可变,需要在 let 后加一个 mut 关键字注明,否则会报错。变量定义后,可以再次用 let 对同名变量进行重新定义(Shadowing),常用与变量的类型转换

具体的使用示例,可以查看本专题的前几个章节,这边就不再赘述了。

需要特别注意的是,let 变量是不能再全局作用域中定义的,通常我们都是在:函数作用域代码块作用域循环作用域 内部使用。如果在全局作用域上使用 let,你将会看到 Rust 抛出的报错:

这也是 Rustletts/js 的中的 let 很大的不同点,在 ts/js 当中,我们可以毫无顾忌的在全局作用域上使用 let 关键字定义些变量并在全局范围内可以随意调用和修改。而到了 Rust ,我们就要改变我们这个使用习惯了,不然得到的只会是 Rust 的无情报错。

变量与常量

typescript当中,可以使用使用 let定义变量,用于存储一些可变的值,同时也可以使用 const 定义常量,用于定义一些永远不变的值。而在 Rust 也是一样的,我们同样可以使用 const 关键字用来定义一些恒定不变的值,即常量。

有同学可能会有疑问,在 Rust 当中,let 在没有声明 mut 的时候,也是不可变的,那不是跟 const 的作用一样了吗?多一个 const 有什么用呢?

  • 不可使用 mut :常量永远都是不可变的,不可以使用 mut 关键字。

  • 使用 const 关键字 :在 Rust 当中,声明常量跟在 typescript 当中声明常量的关键字是一样的,都是 const

  • 类型必须显示标注 :与 typescript 中常量可以根据初始赋值时变量的类型自动推论不同,在 Rust 当中,常量的类型必须显式声明,否则会报错

  • 可在全局作用域中声明 :与 let 不同的是,const 关键字与 ts/js 一样,都可以在全局作用域范围内生命。

  • 常量只能绑定常量表达式:常量只能绑定常量表达式,无法绑定到函数的调用结果,或者是只能在运行时产生的值。

  • 在作用域内持续有效:在程序运行期间,常量在其声明的作用域内是始终有效的。

  • 命名规范 : 在 Rust 当中,常量的命名规范是全大写,多个单词之间使用 _ 分隔,如:FIRST_NAME

    上面的代码其他的应该都很容易理解,有一点比较让人费解的就是 后面的赋值与中的 10_000,或许有些同学不清楚什么意思,这其实是我们在定一个数字的时候,可以用 _ 对数字进行格式化,增加数字的可读性,其实上面的 10_000 就是代表 10000 这个数字。其实这个特性目前也已经被 js 支持了,我们在最新的 chrom 浏览器的控制台,直接使用这种方式定义数值也是能够正常使用的:

变量的隐藏(shadowing)

前端开发的同学应该都很清楚,以下这两种方式,在 JS/TS 中是不允许的:

typescript 复制代码
let num = 10;
// ❌ 不能重复得使用 let 进行同名变量的定义
let num = 20;

const name = "kiner";
// ❌ 不能重复得使用 const 进行同名常量的定义
const name = 18;

然而,在 Rust 当中,将会颠覆你之前的使用习惯:

rust 复制代码
let num: i32 = 10;
// ✅ 这样是合法的,不会报错的,我们在这行之后,num 的类型是 u32,而在这之前,类型则是 i32
let num: u32 = 100;

const NAME: $str = "kiner";
// ✅ 这样是合法的,不会报错的,我们在这行之后,NAME 的类型是 u32,而在这之前,类型则是 &str
const NAME: u32 = 10;

Rust 当中,我们把这种能够重新定义同名变量的特性称之为:Shadowing(隐藏) ,即:变量隐藏。我们在上几篇文章当中,也有初步的接触到变量隐藏的概念,当时是为了实现一个猜数游戏,利用变量隐藏的特性,实现类将字符串类型的用户输入转换成整型的任务。

rust 复制代码
let mut guess = String::new();
    
io::stdin().read_line(&mut guess).expect("读取行失败");

println!("你猜测的数是:{}", guess);

// 类型转换,将原本用户输入的字符串转换成之后方便比较的整型
let guess: i64 = match guess.trim().parse() {
  // 如果转换成功,则将其值赋值给 guess
  Ok(num) => num,
  // 如果转换失败,则使用 continue 关键字跳过本次循环,继续下一次循环,让用户重新输入
  Err(_) => {
    println!("请输入一个数字!");
    continue;
  },
};

总结一下,就是我们可以用后面的 let 关键字定义的同名变量隐藏到前面的同名变量,并且声明的新变量的类型可以跟之前的类型是不一样,如之前是整型,你可以重新声明成字符串类型。

结语

至此,我们已经详细的了解了在 Rust 当中定义变量和常量的方式,也了解了变量的可变性以及 Rust 与其他语言很大的一个不同点:变量隐藏(Shadowing)的概念、使用场景等等,相信大家都已经对变量的相关知识已经更加清晰了吧。

相关推荐
博界IT精灵28 分钟前
主存的扩展及其与CPU的连接(笔记没做完)
笔记·考研
doiito38 分钟前
【安全,架构】RustyVault 项目深度分析报告以及和HashiCorp Vault的差异
后端·安全·rust
Yang_jie_031 小时前
笔记:数据结构(链队列的相关判断条件)
数据结构·笔记
Rockbean1 小时前
10分钟Solana-性能web3-5.4 项目搭建核心环节
rust·web3·智能合约
Rockbean1 小时前
10分钟Solana-性能web3-5.3 项目搭建
rust·web3·智能合约
程序员爱钓鱼2 小时前
Rust 项目目录结构详解:从 Hello World 到企业级项目
后端·rust
2601_9615934212 小时前
Rust 开发环境配置繁琐?RustRover 开箱即用搞定编码调试
开发语言·后端·macos·rust
冬奇Lab14 小时前
每日一个开源项目(第154篇):Warp - 从‘好看的终端‘到 Agentic 开发环境
人工智能·rust·llm
百里香酚兰21 小时前
【python学习笔记】pyttsx3库疑似只播报一次语音
笔记·python·学习
想你依然心痛21 小时前
内存安全语言在嵌入式中的对比:Rust vs Ada vs SPARK——形式化验证、运行时
安全·rust·spark