写点什么

5 分钟速读之 Rust 权威指南(七)

用户头像
码生笔谈
关注
发布于: 2021 年 05 月 21 日
5分钟速读之Rust权威指南(七)

结构体

和元组一样,结构体中的数据可以拥有不同的类型。而和元组不一样的是,结构体需要给每个数据赋予名字以便清楚地表明它们的意义,可以理解为 JS 中的对象。

定义结构体

在创建结构体之前需要先声明结构体和成员的类型,可以理解为 TS 中的 Interface:


struct User {  name: String,  age: i32,}
复制代码


创建结构体:


// 使用mut关键字来使结构体可变,意味着其中的所有数据都会可变let mut user = User {  name: String::from("xiao_ming"),  age: 10,};
// 取值println!("{}", user.name); // "xiao_ming"println!("{}", user.age); // 10
// 修改字段user.age = 11println!("{}", user.age); // 11
复制代码


使用工厂模式创建结构体:


fn user_factory(name: String) -> User {  User {    name, // 属性名和属性值相同时,可以简写    age: 10,  }}
let mut user = user_factory(String::from("xiao_ming"));
println!("{}", user.name); // "xiao_ming"println!("{}", user.age); // 10
复制代码


结构体更新语法,类似于 JS 中的对象合并运算符:


let user = User {  name: String::from("xiao_ming"),  age: 11,}let user2 = User {  age: 10,  ..user // 注意这里的user只能放在其他字段的末尾};println!("{}", user2.name); // "xiao_ming"println!("{}", user2.age); // 10
复制代码


上面 age 输出的是 user2 的 10,而不是 user 的 11,说明结构体更新语法只在 user 中提取 user2 中没有的内容,并不会全部使用 user 进行覆盖。

元组结构体

元组结构体同样是 struct 关键字来定义:


struct Color(u8, u8, u8);struct Point(i32, i32, i32);
复制代码


定义结构体数据:


let black = Color(0, 0, 0);let point = Point(100, 100, 100);
println!("r:{} g:{} b:{}", black.0, black.1, black.2); // r: 0 g: 0 b: 0println!("x:{} y:{} z:{}", point.0, point.1, point.2); // x: 100 y: 100 z: 100
复制代码

空结构体

rust 允许创建没有任何字段的结构体,因为这种结构体与空元组()十分相似,所以也被称为空结构体:


struct Empty;
复制代码

计算长方形面积的案例:

定义一个 area 函数用于计算长方形面积,使用 width 和 height 两个参数表示长方形:


fn area(width: u32, height: u32) -> u32 {  width * height}println!("area: {}", area(100, 100)); // area: 10000
复制代码


使用元组结构体形式:


// 定义一个元组类型的结构体struct Rect (u32, u32);
// 将函数参数改为接收一个Rect类型的参数fn area(rect: &Rect) -> u32 { rect.0 * rect.1}
// 创建一个Rectlet rect = Rect(100, 100);println!("area: {}", area(rect)); // area: 10000
复制代码


使用结构体形式:


// 定义一个普通结构体struct Rect {  width: u32,  height: u32,}fn area(rect: &Rect) -> u32 {  rect.width * rect.height}let rect = Rect {  width: 100,  height: 100,};println!("area: {}", area(rect)); // area: 10000
复制代码

通过派生 trait 增加实用功能

上面有一个问题没有介绍,比如我们尝试直接打印完整结构体:


struct User {  name: String,  age: i32,}let user = {  name: String::from("xiao_ming"),  age: 10};println!("{}", user); // 报错,User无法使用默认格式化程序进行格式化
复制代码


解决这个问题需要两步,第一步,需要添加注解来派生 Debug trait:


#[derive(Debug)]struct User {  name: String,  age: i32,}
复制代码


第二步,添加:?到花括号中,它会告知 println! 当前的结构体需要使用名为 Debug 的格式化输出:


println!("{:?}", user); // User { name: "xiao_ming", age: 10 }
复制代码


使用:#?占位符来增加易读性:


println!("{:?}", user);// User {//   name: "xiao_ming",//   age: 10// }
复制代码


实际上,rust 提供了许多可以通过 derive 注解来派生的 trait,它们可以为自定义的类型增加许多有用的功能,更多信息可以查阅官方文档。

发布于: 2021 年 05 月 21 日阅读数: 10
用户头像

码生笔谈

关注

欢迎关注「码生笔谈」公众号 2018.09.09 加入

前端、Rust干货分享,一起成为更好的Javascripter & Rustacean

评论

发布
暂无评论
5分钟速读之Rust权威指南(七)