变量绑定
变量绑定
使用 let 声明一个变量(声明一个变量相当于告诉 Rust 创建一个变量)。
fn main() {
let my_number = 8;
println!("Hello, number {}", my_number);
}
代码块
变量在代码块 {} 中开始和结束。在此示例中,my_number 在我们调用 println!之前结束,因为它在其自己的代码块内。
fn main() {
{
let my_number = 8; // my_number starts here
// my_number ends here!
}
println!("Hello, number {}", my_number); // ⚠️ there is no my_number and
// println!() can't find it
}
您可以使用代码块返回值:
fn main() {
let my_number = {
let second_number = 8;
second_number + 9 // No semicolon, so the code block returns 8 + 9.
// It works just like a function
};
println!("My number is: {}", my_number);
}
如果在块内添加分号,它将返回 ()(无):
fn main() {
let my_number = {
let second_number = 8; // declare second_number,
second_number + 9; // add 9 to second_number
// but we didn't return it!
// second_number dies now
};
println!("My number is: {:?}", my_number); // my_number is ()
}
可变性
使用 let 声明变量时,该变量是不可变的(无法更改)。这将不起作用:
fn main() {
let my_number = 8;
my_number = 10; // error[E0384]: cannot assign twice to immutable variable my_number.
}
要更改变量,请添加 mut:
fn main() {
let mut my_number = 8;
my_number = 10;
}
但是,即使使用 mut 也不能更改类型。这将不起作用:
fn main() {
let mut my_variable = 8;
my_variable = "Hello, world!"; // expected integer, found &str
}
Shadowing
阴影意味着使用 let 声明一个与另一个变量同名的新变量。它看起来像可变性,但完全不同。阴影看起来像这样:
fn main() {
let my_number = 8; // This is an i32
println!("{}", my_number); // prints 8
let my_number = 9.2; // This is an f64. It is not my_number - it is completely different!
println!("{}", my_number) // Prints 9.2
}
在这里,我们说我们用新的绑定遮盖了 my_number。那么第一个 my_number 是否已销毁?不,但是当我们调用 my_number 时,我们现在得到 my_number f64。并且由于它们在同一个作用域块中,因此我们无法再看到第一个 my_number。但是,如果它们位于不同的块中,则可以同时看到两者。例如:
fn main() {
let my_number = 8; // This is an i32
println!("{}", my_number); // prints 8
{
let my_number = 9.2; // This is an f64. It is not my_number - it is completely different!
println!("{}", my_number) // Prints 9.2
// But the shadowed my_number only lives until here.
// The first my_number is still alive!
}
println!("{}", my_number); // prints 8
}
那么阴影的好处是什么?需要大量更改变量时,阴影效果很好。
fn main() {
let final_number = {
let y = 10;
let x = 9; // x starts at 9
let x = times_two(x); // shadow with new x: 18
let x = x + y; // shadow with new x: 28
x // return x: final_number is now the value of x
};
println!("The number is now: {}", final_number)
}
fn times_two(number: i32) -> i32 {
number * 2
}
没有阴影,即使您不在乎 x,您也必须考虑不同的名称:
fn main() {
// Pretending we are using Rust without shadowing
let final_number = {
let y = 10;
let x = 9; // x starts at 9
let x_twice = times_two(x); // second name for x
let x_twice_and_y = x_twice + y; // third name for x
x_twice_and_y // too bad we didn't have shadowing - we could have just used x
};
println!("The number is now: {}", final_number)
}
fn times_two(number: i32) -> i32 {
number * 2
}
无值变量
没有值的变量称为“未初始化”变量。未初始化表示“尚未开始”。它们很简单,只需命名为:
fn main() {
let my_variable; // ⚠️
}
但是您还不能使用它。您的程序如果尝试使用将无法编译。但是有时候它们会有用。一个好例子是:在以下情况中:您有一个代码块,并且在内部是变量的值,并且该变量需要位于代码块之外。
fn loop_then_return(mut counter: i32) -> i32 {
loop {
counter += 1;
if counter % 50 == 0 {
break;
}
}
counter
}
fn main() {
let my_number;
{
// Pretend we need to have this code block
let number = {
// Pretend there is code here to make a number
7
};
my_number = loop_then_return(number);
}
println!("{}", my_number);
}
重要的是要知道 my_number 是在 main() 函数中声明的,因此它一直存在到最后。但是它从循环内部获得其价值。但是,该值与 my_number 一样长,因为 my_number 具有该值。它有助于想象是否简化了代码。loop_then_return(number)给出结果 50,所以我们将其删除并写 50。另外,现在我们不需要数字,因此我们也将其删除。现在看起来像这样:
fn main() {
let my_number;
{
my_number = 50;
}
println!("{}", my_number);
}