变量和可变性
正如第二章中“使用变量储存值” 部分提到的那样,变量默认是不可改变的(immutable)。这是 Rust 提供给你的众多优势之一,让你得以充分利用 Rust 提供的安全性和简单并发性来编写代码。不过,你仍然可以使用可变变量。让我们探讨一下 Rust 为何及如何鼓励你利用不可变性,以及何时你会选择不使用不可变性。
当变量不可变时,一旦值被绑定一个名称上,你就不能改变这个值。为了对此进行说明,使用 cargo new variables
命令在 projects 目录生成一个叫做 variables 的新项目。
接着,在新建的 variables 目录,打开 src/main.rs 并将代码替换为如下代码,这些代码还不能编译,我们会首次检查到不可变错误(immutability error)。
文件名:src/main.rs
{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/src/main.rs}}
保存并使用 cargo run
运行程序。应该会看到一条与不可变性有关的错误信息,如下输出所示:
{{#include ../listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt}}
这个例子展示了编译器如何帮助你找出程序中的错误。虽然编译错误令人沮丧,但那只是表示程序不能安全的完成你想让它完成的工作;并 不能 说明你不是一个好程序员!经验丰富的 Rustacean 们一样会遇到编译错误。
错误信息指出错误的原因是 不能 对不可变变量 x 二次赋值
(cannot assign twice to immutable variable `x`
),因为你尝试对不可变变量 x
赋第二个值。
在尝试改变预设为不可变的值时,产生编译时错误是很重要的,因为这种情况可能导致 bug。如果一部分代码假设一个值永远也不会改变,而另一部分代码改变了这个值,第一部分代码就有可能以不可预料的方式运行。不得不承认这种 bug 的起因难以跟踪,尤其是第二部分代码只是 有时 会改变值。
Rust 编译器保证,如果声明一个值不会变,它就真的不会变,所以你不必自己跟踪它。这意味着你的代码更易于推导。
不过可变性也是非常有用的,可以用来更方便地编写代码。尽管变量默认是不可变的,你仍然可以在变量名前添加 mut
来使其可变,正如在第二章所做的那样。mut
也向读者表明了其他代码将会改变这个变量值的意图。
例如,让我们将 src/main.rs 修改为如下代码:
文件名:src/main.rs
{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-02-adding-mut/src/main.rs}}
现在运行这个程序,出现如下内容:
{{#include ../listings/ch03-common-programming-concepts/no-listing-02-adding-mut/output.txt}}
通过 mut
,允许把绑定到 x
的值从 5
改成 6
。是否让变量可变的最终决定权仍然在你,取决于在某个特定情况下,你是否认为变量可变会让代码更加清晰明了。
常量
类似于不可变变量,常量 (constants) 是绑定到一个名称的不允许改变的值,不过常量与变量还是有一些区别。
首先,不允许对常量使用 mut
。常量不光默认不可变,它总是不可变。声明常量使用 const
关键字而不是 let
,并且 必须 注明值的类型。在下一部分,