Rust简介
Rust是一种系统编程语言,注重安全性、速度和并发性。它旨在防止许多类型的错误,特别是与内存管理相关的错误。Rust的语法类似于C++,但提供了更好的内存安全性,同时保持高性能。Rust官方文档
设置Rust环境
安装Rust:
Rust可以通过Rustup安装程序进行安装:
按照提示完成安装。安装完成后,可以使用以下命令验证安装:
创建第一个项目:
- 使用Cargo(Rust的包管理和构建系统)创建新项目:
- 进入项目目录:
- 构建并运行项目:
基本语法
Hello, World!
在src
目录下创建一个新的文件main.rs
,并添加以下代码:
使用以下命令运行程序:
变量和可变性
数据类型
Rust是静态类型语言,意味着编译时必须知道所有变量的类型。常见类型包括:
- 标量类型:整数、浮点数、布尔值和字符。
- 复合类型:元组和数组。
Rust 数据类型
以下是Rust中的主要数据类型,以表格形式列出:
数据类型 | 描述 | 示例 |
---|
标量类型 | | |
整数 | 有符号和无符号,大小从8位到128位 | i8 , u8 , i16 , u16 , i32 , u32 , i64 , u64 , i128 , u128 |
浮点数 | 单精度和双精度 | f32 , f64 |
布尔 | 只有两个可能的值:true 或 false | bool |
字符 | 表示单个Unicode字符,4个字节 | char |
复合类型 | | |
元组 | 可以包含多种类型的多个值 | (i32, f64, bool) |
数组 | 每个元素类型相同,固定长度 | [i32; 3] |
控制流
Rust具有常见的控制流结构:if
、else
、loop
、while
和for
。
类型转换
在Rust中,类型转换是一项重要的操作,涉及将一种数据类型的值转换为另一种数据类型。Rust提供了几种不同的类型转换方式,包括隐式转换、显式转换和使用标准库提供的转换特性。
隐式转换
Rust是强类型语言,不支持隐式类型转换。例如,不能将 u32
类型的值直接赋值给 u8
类型的变量:
显式转换
显式转换使用 as
关键字将一个值转换为另一种类型:
使用标准库进行类型转换
Rust标准库提供了一些特性和方法来进行类型转换,例如 From
、Into
、TryFrom
和 TryInto
。
From
和 Into
From
特性用于定义类型的转换方式,Into
特性是 From
的逆操作。如果实现了 From
,则自动实现 Into
。
自定义类型的实现:
TryFrom
和 TryInto
TryFrom
和 TryInto
特性用于可能失败的转换,返回 Result
类型。
字符串与数值类型之间的转换
字符串与数值类型之间的转换可以使用标准库中的 parse
方法和 to_string
方法。
自定义类型之间的转换
可以通过实现 From
、Into
、TryFrom
和 TryInto
特性来定义自定义类型之间的转换。
字符串格式化
在Rust中,字符串格式化有几种常见的方法,以下是每种方法的示例:
这是Rust中最常用的字符串格式化方法,类似于Python的 str.format()
。
2. 使用 println!
宏
这种方法适用于直接输出格式化的字符串。
3. 使用 write!
和 writeln!
宏
这两种宏适用于将格式化字符串写入到实现了 std::fmt::Write
特性的对象中,比如 String
或 Vec<u8>
。
4. 自定义格式化实现
如果需要自定义格式化,可以实现 std::fmt::Display
或 std::fmt::Debug
特性。
这种方法适用于复杂的格式化场景,可以将格式化参数传递给实现了 std::fmt::Write
特性的对象。
所有权和借用
所有权:
Rust中的每个值都有一个唯一的所有者,当所有者超出作用域时,值将被删除。这确保了内存安全而无需垃圾回收。
借用:
函数可以通过引用借用值,而不是获取所有权:
函数
Rust 中的函数是基本的代码组织单元。函数可以接受参数、执行计算并返回值。Rust 的函数具有静态类型,因此所有参数和返回值的类型在编译时必须明确。
函数定义
函数的定义使用 fn
关键字,后面跟随函数名称、参数列表和函数体:
这是一个简单的 main
函数,打印 “Hello, world!”。
带参数的函数
函数可以接受参数,并且每个参数都需要指定类型:
在这个例子中,函数 add
接受两个 i32
类型的参数,并返回它们的和。
返回值的函数
函数可以返回一个值,返回值的类型需要在箭头 ->
之后指定:
函数 square
返回参数 x
的平方。
代码块和表达式
Rust 中的函数体是一个代码块,代码块由花括号包围,最后一个表达式的值会作为函数的返回值,无需使用 return
关键字:
如果使用 return
关键字,必须显式地指定返回值,并且返回语句以分号结束:
函数的可变参数
Rust 不支持直接定义可变参数的函数,但可以通过传递一个包含所有参数的集合(如数组或向量)来实现:
泛型函数
Rust 支持泛型函数,可以接受不同类型的参数。泛型参数用尖括号包围,并在函数名称后面指定:
在这个例子中,largest
函数使用泛型参数 T
,它要求 T
实现了 PartialOrd
trait(表示可以比较大小)。
结构体和枚举
结构体:
结构体用于创建自定义数据类型。
为结构体实现方法和关联函数:
Rust 结构体的初始化
在 Rust 中,结构体的初始化是指创建结构体实例并为其字段分配值。结构体的初始化可以通过直接赋值、构建函数或简便初始化语法来完成。
1. 直接初始化
直接初始化结构体实例时,需要为每个字段赋值:
2. 使用构建函数初始化
可以通过定义一个实现结构体的构建函数来初始化结构体实例。这种方法有助于封装初始化逻辑,并使代码更加简洁。
3. 简便初始化语法(字段初始化简写)
当结构体的字段名与变量名相同时,可以使用简写语法进行初始化:
4. 使用更新语法初始化
如果需要基于现有实例创建新实例,可以使用更新语法:
需要注意的是,user1
中的 username
和 sign_in_count
字段的值被移动到 user2
,因此 user1
在此之后将无法使用。
枚举:
枚举允许通过列举其可能的值来定义一个类型。
错误处理
Rust使用Result
和Option
类型进行错误处理。
Trait
在 Rust 中,trait 是一种定义共享行为的方法。它可以看作是其他语言中的接口,定义了类型必须实现的方法集合。Trait 允许在不同类型之间共享功能,而无需在每个类型中重复实现这些功能。
定义 Trait
定义一个 trait 使用 trait
关键字,后面跟着 trait 名称和方法签名:
实现 Trait
实现一个 trait 使用 impl
关键字,并指定要实现的类型和方法:
你也可以为一个类型实现多个 trait:
默认实现
Trait 方法可以有默认实现,如果某个类型不需要自定义实现,可以使用默认实现:
在这个例子中,NewsArticle
没有提供 summarize
方法的自定义实现,因此会使用默认实现。
Trait 约束
在函数中使用 trait 时,可以对泛型类型参数进行 trait 约束,确保这些类型实现了指定的 trait:
使用 impl Trait
语法,这种方式在参数类型前加上 impl
关键字和 trait 名称,表示任何实现了该 trait 的类型都可以作为参数传递。
可以使用泛型参数和 where
从句来实现更复杂的 trait 约束:
Trait 对象
Trait 对象允许在运行时进行动态分发。可以使用指向 trait 对象的引用 (&dyn Trait
) 或智能指针 (Box<dyn Trait>
):