你将学习的一个要点是_变量绑定_。它们看起来像这样:
~~~
fn main() {
let x = 5;
}
~~~
在每个例子中都写上`fn main() {`有点冗长,所以之后我们将省略它。如果你是一路看过来的,确保你写了`main()`函数,而不是省略不写。否则,你将得到一个错误。
在许多语言中,这叫做_变量_。不过Rsut的变量绑定有自己的玄机。例如`let`表达式的左侧是一个“[模式](http://doc.rust-lang.org/nightly/book/patterns.html)”,而不仅仅是一个变量。这意味着我们可以这样写:
~~~
let (x, y) = (1, 2);
~~~
在这个表达式被计算后,`x`将会是1,而`y`将会是2.模式非常强大,并且本书中有[关于它的部分](http://doc.rust-lang.org/nightly/book/patterns.html)。我们现在还不需要这些功能,所以接下来你只需记住有这个东西就行了。
Rust是一个静态类型语言,这意味着我们需要先确定我们需要的类型。那为什么我们第一例子能编译过呢?嘛,Rust有一个叫做_类型推断_的功能。如果它能确认这是什么类型,Rust不需要你非要把它写出来。
若你愿意,我们也可以加上类型。类型写在一个冒号(:)后面:
~~~
let x: i32 = 5;
~~~
如果我叫你对着全班同学大声读出这一行,你应该大喊“`x`被绑定为`i32类`型,它的值是`5`”。
在这个例子中我们选择`x`代表一个32位的有符号整数。Rust有许多不同的原生整数类型。以`i`开头的代表有符号整数而`u`开头的代表无符号整数。可能的整数大小是8,16,32和64位。
在之后的例子中,我们可能会在注释中注明变量类型。例子看起来像这样:
~~~
fn main() {
let x = 5; // x: i32
}
~~~
注意注释和`let`表达式有类似的语法。理想的Rust代码中不应包含这类注释。不过我们偶尔会这么做来帮助你理解Rust推断的是什么类型。
绑定默认是_不可变的_(_immutable_)。下面的代码将不能编译:
~~~
let x = 5;
x = 10;
~~~
它会给你如下错误:
~~~
error: re-assignment of immutable variable `x`
x = 10;
^~~~~~~
~~~
如果你想一个绑定是可变的,使用`mut`:
~~~
let mut x = 5; // mut x: i32
x = 10;
~~~
不止一个理由使得绑定默认不可变的,不过我们可以理解它通过一个Rust的主要目标:安全。如果你没有使用`mut`,编译器会捕获它,让你知道你改变了一个你可能并不打算让它改变的值。如果绑定默认是可变的,编译器将不可能告诉你这些。如果你确实想变量可变,解决办法也非常简单:加个`mut`。
尽量避免可变状态有一些其它好处,不过这不在这个教程的讨论范围内。大体上,你总是可以避免显式可变量,并且这也是Rust希望你做的。即便如此,有时,可变量是你需要的,所以这并不是被禁止的。
让我们回到绑定。Rust变量绑定有另一个不同于其它语言的方面:绑定要求在可以使用它之前必须初始化。
让我们尝试一下。将你的`src/main.rs`修改为为如下:
~~~
fn main() {
let x: i32;
println!("Hello world!");
}
~~~
你可以用`cargo build`命令去构建它。它依然会输出“Hello, world!”,不过你会得到一个警告:
~~~
Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world)
src/main.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variable)] on by default
src/main.rs:2 let x: i32;
^
~~~
Rust警告我们从未使用过这个变量绑定,但是因为我们从未用过它,无害不罚。然而,如果你确实想使用`x`,事情就不一样了。让我们试一下。修改代码如下:
~~~
fn main() {
let x: i32;
println!("The value of x is: {}", x);
}
~~~
然后尝试构建它。你会得到一个错误:
~~~
$ cargo build
Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world)
src/main.rs:4:39: 4:40 error: use of possibly uninitialized variable: `x`
src/main.rs:4 println!("The value of x is: {}", x);
^
note: in expansion of format_args!
<std macros>:2:23: 2:77 note: expansion site
<std macros>:1:1: 3:2 note: in expansion of println!
src/main.rs:4:5: 4:42 note: expansion site
error: aborting due to previous error
Could not compile `hello_world`.
~~~
Rust是不会让我们使用一个没有经过初始化的值的。接下来,让我们讨论一下我们添加到`println!`中的内容。
如果你输出的字符串中包含一对大括号(`{}`,一些人称之为。。胡须(moustaches)?),Rust将把它解释为插入值的请求。_字符串插值_(_String interpolation_)是一个计算机科学术语,代表“在字符串中插入值”。我们加上一个逗号,然后是一个`x`,来表示我们想插入`x`的值。逗号用来分隔我们传递给函数和宏的参数,如果你想传递多个参数的话。
当你只写了大括号的时候,Rust会尝试检查值的类型来显示一个有意义的值。如果你想指定详细的语法,这里有[很多选项可供选择](http://doc.rust-lang.org/std/fmt/)。现在,让我们保持默认,整数并不难打印。
- 前言
- 1.介绍
- 2.准备
- 2.1.安装Rust
- 2.2.Hello, world!
- 2.3.Hello, Cargo!
- 3.学习Rust
- 3.1.猜猜看
- 3.2.哲学家就餐问题
- 3.3.其它语言中的Rust
- 4.高效Rust
- 4.1.栈和堆
- 4.2.测试
- 4.3.条件编译
- 4.4.文档
- 4.5.迭代器
- 4.6.并发
- 4.7.错误处理
- 4.8.外部语言接口
- 4.9.Borrow 和 AsRef
- 4.10.发布途径
- 5.语法和语义
- 5.1.变量绑定
- 5.2.函数
- 5.3.原生类型
- 5.4.注释
- 5.5.If语句
- 5.6.for循环
- 5.7.while循环
- 5.8.所有权
- 5.9.引用和借用
- 5.10.生命周期
- 5.11.可变性
- 5.12.结构体
- 5.13.枚举
- 5.14.匹配
- 5.15.模式
- 5.16.方法语法
- 5.17.Vectors
- 5.18.字符串
- 5.19.泛型
- 5.20.Traits
- 5.21.Drop
- 5.22.if let
- 5.23.trait对象
- 5.24.闭包
- 5.25.通用函数调用语法
- 5.26.包装箱和模块
- 5.27.`const`和`static`
- 5.28.属性
- 5.29.`type`别名
- 5.30.类型转换
- 5.31.关联类型
- 5.32.不定长类型
- 5.33.运算符和重载
- 5.34.`Deref`强制多态
- 5.35.宏
- 5.36.裸指针
- 6.Rust开发版
- 6.1.编译器插件
- 6.2.内联汇编
- 6.3.不使用标准库
- 6.4.固有功能
- 6.5.语言项
- 6.6.链接参数
- 6.7.基准测试
- 6.8.装箱语法和模式
- 6.9.切片模式
- 6.10.关联常量
- 7.词汇表
- 8.学院派研究
- 勘误