Rust 快速入门60分① 看完这篇就能写代码了

简介: Rust 快速入门60分① 看完这篇就能写代码了

一、变量与常量


1.1 变量


1.1.1. 变量命名


变量名由字母、数字或下划线组成,应该具有描述性,能够清楚地表达变量的含义。命名的基本规则和大多数编程语言基本相同,有些细节上稍微有所不同。规则如下:


   变量名必须以字母或下划线开头。


   变量名不能以数字开头。


   变量名区分大小写,推荐使用 snake_case 规则(字母全部小写和下划线)。


   禁止使用和 Rust 关键字同名的变量名。


   避免使用和 Rust 标准库中已有的函数、类型或模块同名的变量名。


   对于私有变量 (private variables),可以使用 _ 作为前缀,区分开公共变量和私有变量。




1.1.2. 变量声明、赋值

Rust 变量声明使用 let 关键字,有些早期版本的basic语言也用LET(现在通常是DIM)

示例:

fn main() {
    let x = 323;
    let y = 3.23;
    print!("x: {}, ", x);
    println!("y: {}", y);
    //输出 x: 323, y: 3.23
}


上面示例中,fn 是函数 function 的缩写,表示 main() 是这个rust程序的主函数;


let 变量名 = 常数;就是一个变量声明、赋值语句;


print!() 和 println!() 是打印的“宏”,宏不是函数,但功能也就相近于Java中的System.out.print()函数和System.out.println()函数的功能,两者输出差一个换行符。


// 表示注释语句,注释与C++相同,行注释用 //,块注释用 /*  */;Rust另外还有文档注释。


函数体中每一行都是一个语句(当然语句也可以跨多行表达),语句由各种表达式组成。第一条语句必须有标点符号分号作结尾,表达式一般没有符号作结尾的。关于Rust中的“宏”,它和C/C++中的“宏”还是不同的,更多函数相关内容,放到之后的函数章节再讲。


let 语句也可以分成两行,先声明再分配值(赋值绑定):

fn main() {
    let x;
    x = 100;
    println!("x: {}", x); 
}


let 语句还可以一行赋值多个变量,但要加上括号(其实是复合数据类型之一的元组):

fn main() {
    let (x, y) = (3, 4);
    let z = (x*x+y*y) as f64;
    let z = z.sqrt().round() as i32;
    println!("{},{},{}", x, y, z); // 3,4,5
    let (a, b, c) = (1, 2, 3);
    println!("{},{},{}", a, b, c); // 1,2,3
}


其中,as 也是Rust关键字之一,在这里用于强制转换数据类型。  

sqrt()、round() 分别为平方根、取整函数。



1.1.3. Snake case

Snake case 是一种命名规范,它使用小写字母,单词之间用下划线 "_" 连接。

Rust不推荐在变量中有大写字母,示例如下:


fn main() {
    let Int = 100;
    let My_Integer = 200;
    let my_integer = 300;
    println!("{} {} {}", Int, My_Integer, my_integer)
}


以上代码可以编译执行,但会有警告出现:

···Rust
warning: variable `Int` should have a snake case name
 --> D:\Rust\hello.rs:2:9
   |
2 |     let Int = 100;
   |         ^^^ help: convert the identifier to snake case (notice the capitalization): `int`
   |
  = note: `#[warn(non_snake_case)]` on by default
warning: variable `My_Integer` should have a snake case name
 --> D:\Rust\hello.rs:3:9
   |
3 |     let My_Integer = 200;
   |         ^^^^^^^^^^ help: convert the identifier to snake case: `my_integer`
warning: 2 warnings emitted
100 200 300
···



1.1.4. 禁止使用和避免使用

变量命名使用关键字,报错通不过编译,所以是禁止使用;但与标准库中已有的函数、类型同名,只是容易混淆,但编译不警告不报错,所以只能说是避免使用。如:

fn main() {
    //let fn = 10; //禁止使用
    //let let = 2; //禁止使用
    let u8 = 10u8; //避免使用
    let pow;       //避免使用
    pow = u8.pow(2);
    println!("{} {}", u8, pow)  //输出 10 100
}

其中, u8 的变量类型是8位无符号整型,pow() 是标准库函数平方幂函数。

函数名、类型名称作变量名不会报错,而fn, let关键字作变量名则报错:

```Rust

expected identifier, found keyword

 |

help: escape `fn` to use it as an identifier  

```



1.1.5 匿名变量



下划线 _ 是一个特殊的变量名,更确切地说是变量名称的缺失,就称它为匿名变量。它的基本意思是舍弃,可以理解为废纸篓,这个变量扔掉不要了,不能被再次调用。(Go, Python里也有  _ 用作匿名变量,但细节各不相同,而且在python里 “_ = 5;print(_)” 是合法的)


fn main() {
    let (a,_) = (6,2);
    println!("{}", a);
    //println!("{}", _); //报错^ `_` not allowed here
}




1.2 基本数据类型


1.2.1 整型


Rust整型 分为有符号整型(signed,标记 in)和无符号整型(unsigned,标记 un),区别在于数字是否有负数。带符号整型的安全存储范围为 -2^(n-1) 到 2^(n-1) - 1,无符号整型的安全存储范围为 0 到 2^n,n 为数据位长度,见下表:

image.png


isize 和 usize 是根据系统架构决定的,例如带符号整型,如果系统是 64 位,类型为 i64,如果系统是 32 位,类型为 i32。(这和C++中的size_t类型相似)


指定类型和默认类型


变量声明时,可以先指定类型,再分配绑定数值,变量名后面使用冒号跟随类型来明确指定变量的类型,称为显式指定;Rust 是强类型语言,具有自动判断变量类型的能力,可理解为这是隐式指定。以下示例中声明的变量 z 并没有明确指定其具体类型,则默认为 i32 类型,这也是 Rust 的特性之一类型推断。

fn main() {
    let x: u8;
    x = 123;
    let y = -1000i64;
    let z = -323;  //不指定类型,默认为i32
    println!("x: {}, y: {}, z: {}", x, y, z);
}


1.2.2 浮点型

Rust浮点型 分为 32 位浮点数(f32)和 64 位浮点数(f64)。浮点型若不指定具体类型,则默认为 f64 浮点数,现在的高性能CPU对两种浮点数计算的速度几乎相同,但 64 位浮点数精度更高。

fn main() {
    let x: f32;
    x = 1.23;
    let y: f64 = 3.23;
    let z = -3.23;  //不指定类型,默认为f64
    println!("x: {}, y: {}, z: {}", x, y, z);
}


1.2.3 字符型

Rust字符型 是一个4字节 Unicode 码,支持中文等非英文字符,使用单引号''包括。

fn main() {
    let a = 'a';
    let b: char = '字';
    let c = '😊';
    println!("a: {}, b: {}, c: {}", a, b, c); 
}


1.2.4 布尔型

Rust布尔型 用 bool 表示,占用1个字节,值只能为 true 或 false,全小写非大写字母开头。(输出与声明同形,不像C/C++只能输出1和0

fn main() {
    let x = true;
    let y: bool = false;
    println!("x: {}, y: {}", x, y); //输出 x: true, y: false
}



1.3 变量的可变和不可变


1.3.1 不可变变量

先看一个实例:

fn main() {
    let x = 6;
    x = x + 1;  // 报错
    println!("{}", x)
}


在大多数编程语言中,上述实例应该打印出 7,但在Rust语言里却是报错:

```Rust
error[E0384]: cannot assign twice to immutable variable `x`
 --> D:\Rust\hello.rs:3:5
   |
2 |     let x = 6;
   |         -
   |         |
   |         first assignment to `x`
   |         help: consider making this binding mutable: `mut x`
3 |     x = x + 1;
   |     ^^^^^^^^^ cannot assign twice to immutable variable
```


意思就是: 不能为不可变变量`x赋值两次`,并提示考虑绑定可变:`mut x`

特别之处: Rust变量是不可变的!

通常来说变量将是可变的,但是在 Rust 中预设变量却是不可变的。Rust 鼓励使用不可变变量,当然如果明确知道该变量是可变得,就得用关键字 mut 附加说明它是可变的变量。



1.3.2 可变变量

可变变量要用 let mut 两个关键字来声明,示例如下:


1. fn main() {
2. let mut x = 6;  // 可变变量声明要在let后附加mut关键字
3.     x = x + 1;
4. println!("{}", x)  // 输出 7
5. }



1.3.4 静态变量(全局变量)

静态变量用 static 声明的变量的生命周期是整个程序,从启动到退出。这也是Rust中唯一的声明全局变量的方法。它的生命周期永远是'static, 它占用的内存空间也不会在执行过程中回收。


注意点:


1. 全局变量必须在声明的时候马上初始化;

2. 命名时字母要全部大写,否则编译有警告信息;

3. 全局变量的初始化必须是编译期就能确定的常量;

4. 带有 mut 修饰的全局变量,在使用的时候必须使用 unsafe 关键字;

5. 全局变量可以写到函数外面,被任意一个函数使用。


fn main() {
    static G1 : i32 = 3;
    println!("{}, {}", G1, G1 + 20);
    static mut G2 : i32 = 4;
    unsafe {
        // G1 = 2; // cannot assign to immutable static item `G1`
        G2 = G1 + 5;
        println!("{}, {}", G1, G2);
    }
}
/* 输出
3, 23
3, 8
*/




1.4 常量

常量,和变量一样都是用来存储数据的标识符,常量使用 const 关键字声明。常量的值是不可变的,不允许使用mut关键字修饰这个变量绑定。



1.4.1 常量命名

常量的命名规则和方法与静态变量基本类似,命名时字母也要全部大写

错误示例:常量字母不全部大写可以通过编译,但有警告信息。

const pi:f32 = 3.14159; //报错
const Pi:f32 = 3.14159; //报错
fn main() {
    println!("{}", pi);
    println!("{}", Pi);
}


```
warning: constant `pi` should have an upper case name
 --> D:\Cpp\hello.rs:1:7
   |
1 | const pi:f32 = 3.14159;
   |       ^^ help: convert the identifier to upper case: `PI`
   |
  = note: `#[warn(non_upper_case_globals)]` on by default
warning: constant `Pi` should have an upper case name
 --> D:\Cpp\hello.rs:2:7
   |
2 | const Pi:f32 = 3.14159;
   |       ^^ help: convert the identifier to upper case (notice the capitalization): `PI`
warning: 2 warnings emitted
3.14159
3.14159
```




1.4.2 常量用法

常量必须显式指定类型以及声明同时就赋值,并且常量的值必须是编译时可确定的常数或者是常量表达式。示例如下:

const PI: f64 = 3.14159;
const FLAG: bool = true;
const HOURS: u32 = 12;
const SECONDS: u32 = 60 * 60 * HOURS;
const MIN_NUM: i32 = 1 << 31;
const MAX_NUM: i32 = -(1 + MIN_NUM);
fn main() {
    println!("{}", PI);
    println!("{}", FLAG);
    println!("{}", HOURS);
    println!("{}", SECONDS);
    println!("{}", MIN_NUM);
    println!("{}", MAX_NUM);
}
/* 输出:
3.14159
true
12
43200
-2147483648
2147483647
*/



错误示例:常量不可以隐式赋值,或者先声明后赋值。

const PI = 3.14159; //报错
const FLAG:bool;  //报错
fn main() {
    FLAG = true;  //报错
    println!("{}", PI);
    println!("{}", FLAG);
}



```
error: free constant item without body
 --> D:\Cpp\hello.rs:2:1
   |
2 | const FLAG:bool;
   | ^^^^^^^^^^^^^^^-
   |                |
   |                help: provide a definition for the constant: `= <expr>;`
error: missing type for `const` item
 --> D:\Cpp\hello.rs:1:9
   |
1 | const PI = 3.14159;
   |         ^ help: provide a type for the constant: `: f64`
error[E0070]: invalid left-hand side of assignment
 --> D:\Cpp\hello.rs:5:10
   |
5 |     FLAG = true;
   |     ---- ^
   |     |
   |     cannot assign to this expression
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0070`. 
``` 



1.4.3 标准库常量

引用标准库中的常量,使用关键字 use 来导入。(类似 java和python 中 import

比如std::f32或std::f64中的一些数学常量:

use std::f32::consts::PI;
use std::f32::consts::FRAC_1_PI;
use std::f32::consts::FRAC_2_PI;
use std::f32::consts::SQRT_2;
use std::f32::consts::FRAC_1_SQRT_2;
use std::f32::consts::E;
use std::f32::consts::LN_2;
use std::f32::consts::LOG2_E;
use std::f32::consts::LOG10_E;
fn main() {
    println!("{}", PI); 
    println!("{}", FRAC_1_PI);
    println!("{}", FRAC_2_PI);
    println!("{}", SQRT_2);
    println!("{}", FRAC_1_SQRT_2);
    println!("{}", E);
    println!("{}", LN_2);
    println!("{}", LOG2_E);
    println!("{}", LOG10_E);
}
/* 输出
3.1415927
0.31830987
0.63661975
1.4142135
0.70710677
2.7182817
0.6931472
1.442695
0.4342945
改std::f64,则输出
3.141592653589793
0.3183098861837907
0.6366197723675814
1.4142135623730951
0.7071067811865476
2.718281828459045
0.6931471805599453
1.4426950408889634
0.4342944819032518
*/



1.5 本章小结


1. 变量(Variables):在 Rust 中,变量默认是不可变的(immutable),也就是说,一旦被赋值后,就不能再修改其值。如果需要修改变量的值,需要使用 `mut` 关键字来声明可变变量。


2. 常量(Constants):与变量不同,常量在声明后就不能再修改其值。在 Rust 中,使用 `const` 关键字来声明常量,常量的命名规则与变量相同,但必须使用大写字母命名,并且必须在声明时就赋值。


3. 可变绑定(Mutable bindings):除了使用 `mut` 关键字来声明可变变量外,还可以使用 `let` 关键字来声明一个可变绑定。可变绑定允许我们在不改变绑定本身的情况下修改绑定所指向的值。


4. 类型推断(Type inference):Rust 支持类型推断,也就是说,可以在声明变量或常量时省略类型,由编译器自动推断类型。例如,可以使用 `let x = 42;` 来声明一个整数变量,编译器会自动推断出 x 的类型为 i32。


5. 变量遮蔽(Variable shadowing):Rust 中可以使用相同的名称来声明一个新的变量或常量,这会遮蔽之前的变量或常量。这个特性可以用来在不改变原有代码的情况下修改变量的值或类型。


6. 变量的作用域由声明的位置开始,直到当前作用域的结束;变量在离开作用域后会被自动销毁。常量在整个程序运行期间都存在。


注:本文中所有代码都可以在Rust官方线上编译器里编译通过。





目录
相关文章
|
2月前
|
存储 Rust 监控
Rust代码编写高性能屏幕监控软件的核心算法
本文介绍了使用Rust编写的高性能屏幕监控软件的实现方法。核心算法包括:1) 使用`image`和`winit`库捕获并转换屏幕图像;2) 对图像进行处理,检测特定对象或活动;3) 利用Rust的并发性并行处理多个帧以提高效率;4) 提取数据后,通过`reqwest`库自动提交到网站进行分析或存储。通过结合Rust的高性能和丰富的库,可构建满足各种需求的高效屏幕监控工具。
138 5
|
2月前
|
Rust 安全 编译器
Rust中的Raw Pointers与不安全代码:深入探索与最佳实践
本文旨在探讨Rust编程语言中Raw Pointers(原始指针)的使用场景以及如何安全地编写不安全代码。我们将深入了解Raw Pointers的定义、工作原理以及它们在Rust中的用途,同时还将讨论编写不安全代码的最佳实践和注意事项,以确保代码的稳定性和安全性。
|
9天前
|
Rust 编译器
Rust代码组织:Package、Crate、Module
Rust代码组织:Package、Crate、Module
5 0
|
1月前
|
监控 Rust 安全
Rust代码在公司电脑监控软件中的内存安全监控
使用 Rust 语言开发的内存安全监控软件在企业中日益重要,尤其对于高安全稳定性的系统。文中展示了如何用 Rust 监控内存使用:通过获取向量长度和内存大小来防止泄漏和溢出。此外,代码示例还演示了利用 reqwest 库自动将监控数据提交至公司网站进行实时分析,以保证系统的稳定和安全。
121 2
|
2月前
|
Rust 安全 测试技术
Rust并发编程实践:快速入门系统级编程
Rust是一门现代的系统编程语言,它的设计目标是提供安全性、并发性和高性能。Rust的出现是为了解决其他编程语言在这些方面存在的一些问题和挑战。
|
2月前
|
Rust 安全 编译器
Rust中的不安全代码:挑战与注意事项
Rust语言以其内存安全和性能优势著称,但在某些情况下,开发者可能需要使用不安全代码。本文将探讨Rust中不安全代码的使用场景,并详细分析使用不安全代码时需要注意的关键事项,以确保代码的安全性和稳定性。
|
2月前
|
JSON 编解码 Rust
Rust 模块化:深入了解 Rust 中的代码组织
关键字`mod、pub、crate、self、super、use`都表示什么含义,如何使用?
|
Rust C++
Rust语言入门以及代码示例
Rust语言是一种系统级编程语言,它具有高性能、安全性和并发性。Rust的设计目标是为了解决C++语言中存在的安全问题和内存泄漏等问题。Rust语言由Mozilla开发,并于2010年首次发布。
386 0
Rust语言入门以及代码示例
|
Rust 编译器
Rust中如何复用代码?
Rust中如何复用代码?
|
Rust 安全 Java
【Rust指南】快速入门|开发环境|hello world
【Rust指南】快速入门|开发环境|hello world
234 0
【Rust指南】快速入门|开发环境|hello world