Rust

2025年07月12日更新 6 人订阅
原价: ¥ 6 限时优惠
专栏简介 Rust编程语言之错误处理 Rust 语言之 flod Rust编程语言之Cargo、Crates.io详解 Rust编程语言之枚举与模式匹配 Rust语言 - 接口设计的建议之受约束(Constrained) Rust编程语言之无畏并发 Rust语言 - 接口设计的建议之灵活(flexible) Rust语言 - 接口设计的建议之显而易见(Obvious) Rust语言 - 接口设计的建议之不意外(unsurprising) Rust 实战:构建实用的 CLI 工具 HTTPie Rust编程语言学习之高级特性 Rust内存管理揭秘:深度剖析指针与智能指针 解决Rust中数组和切片的编译时大小问题 《Rust编程之道》学习笔记一 Rust Async 异步编程 简易教程 使用 Async Rust 构建简单的 P2P 节点 Rust编程语言入门之模式匹配 Rust async 编程 Rust编程语言之编写自动化测试 Rust编程语言之函数式语言特性:迭代器和闭包 《Rust编程之道》学习笔记二 Rust Tips 比较数值 使用 Rust 开发一个微型游戏 Rust编程初探:深入理解Struct结构体 深入理解Rust中的内存管理:栈、堆与静态内存详解 深入理解 Rust 结构体:经典结构体、元组结构体和单元结构体的实现 深入掌握 Rust 结构体:从模板到实例化的完整指南 深入理解Rust中的结构体:逻辑与数据结合的实战示例 深入理解 Rust 枚举:从基础到实践 掌握Rust字符串的精髓:String与&str的最佳实践 全面解析 Rust 模块系统:实战案例与应用技巧 Rust 中的 HashMap 实战指南:理解与优化技巧 掌握Rust模式匹配:从基础语法到实际应用 Rust 中的面向对象编程:特性与实现指南 深入理解 Rust 的 Pin 和 Unpin:理论与实践解析 Rust Trait 与 Go Interface:从设计到实战的深度对比 从零开始:用 Rust 和 Axum 打造高效 Web 应用 Rust 错误处理详解:掌握 anyhow、thiserror 和 snafu Rust 如何优雅实现冒泡排序 链表倒数 K 节点怎么删?Python/Go/Rust 实战 用 Rust 玩转数据存储:JSON 文件持久化实战 Rust实战:打造高效字符串分割函数 如何高效学习一门技术:从知到行的飞轮效应 Rust 编程入门:Struct 让代码更优雅 Rust 编程:零基础入门高性能开发 用 Rust 写个猜数游戏,编程小白也能上手! Rust 入门教程:变量到数据类型,轻松掌握! 深入浅出 Rust:函数、控制流与所有权核心特性解析 从零开始:用 Rust 和 Axum 打造高效 Web 服务 Rust 集合类型解析:Vector、String、HashMap 深入浅出Rust:泛型、Trait与生命周期的硬核指南 Rust实战:博物馆门票限流系统设计与实现 用 Rust 打造高性能图片处理服务器:从零开始实现类似 Thumbor 的功能 Rust 编程入门实战:从零开始抓取网页并转换为 Markdown 深入浅出 Rust:高效处理二进制数据的 Bytes 与 BytesMut 实战 Rust智能指针:解锁内存管理的进阶之道 用 Rust 打造命令行利器:从零到一实现 mini-grep 解锁Rust代码组织:轻松掌握Package、Crate与Module Rust 所有权:从内存管理到生产力释放 深入解析 Rust 的面向对象编程:特性、实现与设计模式 Rust + Protobuf:从零打造高效键值存储项目 bacon 点燃 Rust:比 cargo-watch 更爽的开发体验 用 Rust 打造微型游戏:从零开始的 Flappy Dragon 开发之旅 函数式编程的Rust之旅:闭包与迭代器的深入解析与实践 探索Rust编程之道:从设计哲学到内存安全的学习笔记 精读《Rust编程之道》:吃透语言精要,彻底搞懂所有权与借用 Rust 避坑指南:搞定数值比较,别再让 0.1 + 0.2 != 0.3 困扰你! 告别 Vec!掌握 Rust bytes 库,解锁零拷贝的真正威力 告别竞态条件:基于 Axum 和 Serde 的 Rust 并发状态管理最佳实践 Rust 异步编程实践:从 Tokio 基础到阻塞任务处理模式 Rust 网络编程实战:用 Tokio 手写一个迷你 TCP 反向代理 (minginx) 保姆级教程:Zsh + Oh My Zsh 终极配置,让你的 Ubuntu 终端效率倍增 不止于后端:Rust 在 Web 开发中的崛起之路 (2024数据解读) Rust核心利器:枚举(Enum)与模式匹配(Match),告别空指针,写出优雅健壮的代码 Rust 错误处理终极指南:从 panic! 到 Result 的优雅之道 想用 Rust 开发游戏?这份超详细的入门教程请收好!

Rust 编程入门:Struct 让代码更优雅

Rust编程入门:Struct让代码更优雅想写出简洁又高效的代码?Rust的Struct带你轻松入门!在Rust编程世界中,Struct(结构体)是组织数据、提升代码质量的利器。无论是定义用户资料、计算几何面积,还是构建复杂逻辑,Struct都能让你的代码更优雅、更清晰。本文将从

Rust 编程入门:Struct 让代码更优雅

想写出简洁又高效的代码?Rust 的 Struct 带你轻松入门! 在 Rust 编程世界中,Struct(结构体)是组织数据、提升代码质量的利器。无论是定义用户资料、计算几何面积,还是构建复杂逻辑,Struct 都能让你的代码更优雅、更清晰。本文将从零开始,带你掌握 Struct 的定义、实例化、方法实现及优化技巧,通过直观的示例和实用代码,助你快速上手 Rust 编程。无论你是编程新手还是进阶开发者,这篇入门指南都将为你打开 Rust 的新大门!快来一起探索吧!

本文是 Rust 编程初学者的 Struct 入门指南,深入浅出地讲解了 Struct 的核心概念与实用技巧。内容涵盖 Struct 的定义与实例化、字段访问与更新、Tuple Struct 和 Unit-Like Struct 的特性,以及方法和关联函数的实现。通过计算长方形面积的案例,展示了如何用 Struct 优化代码,提升可读性和性能。文章还介绍了调试技巧(如 #[derive(Debug)])和所有权机制,配以清晰的代码示例,帮助读者快速掌握 Struct 的优雅用法。无论你是 Rust 新手还是想提升代码质量的开发者,本文都为你提供了实用的学习路径。

一、定义并实例化struct

什么是 struct

  • struct,结构体
    • 自定义的数据类型
    • 为相关联的值命名,打包 => 有意义的组合

定义 struct

  • 使用 struct 关键字,并为整个struct命名
  • 在花括号内,为所有字段(Field)定义名称和类型

例如:

struct User {
  username: String,
  email: String,
  sign_in_count: u64,
  active: bool,
}

实例化struct

  • 想要使用struct,需要创建struct的实例:
    • 为每个字段指定具体值
    • 无需按声明的顺序进行指定

例子:

let user1 = User {
  email: String::from("someone@example.com"),
  username: String::from("someusername123"),
  active: true,
  sign_in_count: 1,
};

代码:

struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

fn main() {
    println!("Hello, world!");

    let user1 = User {
        email: String::from("user1@example.com"),
        username: String::from("user1"),
        active: true,
        sign_in_count: 556,
    };
}

取得struct里面的某个值

  • 使用点标记法:
let mut user1 = User {
  email: String::from("someone@example.com"),
  username: String::from("someusername123"),
  active: true,
  sign_in_count: 1,
};

user1.email = String::from("anotheremail@example.com");

注意

  • 一旦struct的实例是可变的,那么实例中所有的字段都是可变的

struct 作为函数的返回值

例子:

fn build_user(email: String, username: String) -> User {
  User {
    email: email,
    username: username,
    active: true,
    sign_in_count: 1,
  }
}

字段初始化简写

  • 当字段名与字段值对应变量名相同时,就可以使用字段初始化简写的方式:
fn build_user(email: String, username: String) -> User {
  User {
    email,
    username,
    active: true,
    sign_in_count: 1,
  }
}

Struct 更新语法

  • 当你想基于某个struct实例来创建一个新实例的时候,可以使用struct更新语法:
let user2 = User {
  email: String::from("another@example.com"),
  username: String::from("anotherusername567"),
  active: user1.active,
  sign_in_count: user1.sign_in_count,
};

let user2 = User {
  email: String::from("another@example.com"),
  username: String::from("anotherusername567"),
  ..user1
};

Tuple struct

  • 可定义类似 tuple 的struct,叫做 tuple struct
    • Tuple struct 整体有个名,但里面的元素没有名
    • 适用:想给整个 tuple起名,并让它不同于其它tuple,而且又不需要给每个元素起名
  • 定义 tuple struct:使用 struct 关键字,后边是名字,以及里面元素的类型
  • 例子:
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
  • black 和 origin 是不同的类型,是不同 tuple struct 的实例

Unit-Like Struct (没有任何字段)

  • 可以定义没有任何字段的 struct,叫做 Unit-Like struct(因为与(),单元类型类似)
  • 适用于需要在某个类型上实现某个Trait,但是在里面又没有想要存储的数据

struct 数据的所有权

struct User {
  username: String,
  email: String,
  sign_in_count: u64,
  active: bool,
}
  • 这里的字段使用了String 而不是 &str:
    • 该 struct 实例拥有其所有的数据
    • 只要 struct 实例是有效的,那么里面的字段数据也是有效的
  • struct 里也可以存放引用,但这需要使用生命周期
    • 生命周期保证只要struct实例是有效的,那么里面的引用也是有效的
    • 如果 struct 里面存储引用,而不使用生命周期,就会报错
// 没有使用生命周期
struct User {
  username: &str,
  email: &str,
  sign_in_count: u64,
  active: bool,
}

fn main() {
  println!("Hello, world!");

  let user1 = User {
    email: "fdsa",
    username: "fds",
    active: true,
    sign_in _count: 556,
  };
}

二、 struct 例子

例子需求

  • 计算长方形面积
fn main() {
    let w = 30;
    let l = 50;

    println!("{}", area(w, l));
}

fn area(width: u32, length: u32) -> u32 {
    width * length
}

优化一:

fn main() {
    let rect = (30, 50);

    println!("{}", area(rect));
}

fn area(dim: (u32, u32)) -> u32 {
    dim.0 * dim.1
}

优化二:

struct Rectangle {
    width: u32,
    length: u32,
}

fn main() {
    let rect = Rectangle {
        width: 30,
        length: 50,
    };

    println!("{}", area(&rect));
}

fn area(rect: &Rectangle) -> u32 {
    rect.width * rect.length
}

什么是struct

  • std::fmt::Display
  • std::fmt::Debug
  • #[derive(debug)]
  • {:?}
  • {:#?}
#[derive(Debug)]
struct Rectangle {
    width: u32,
    length: u32,
}

fn main() {
    let rect = Rectangle {
        width: 30,
        length: 50,
    };

    println!("{}", area(&rect));

    println!("{:?}", rect);
    println!("{:#?}", rect);
}

fn area(rect: &Rectangle) -> u32 {
    rect.width * rect.length
}

Struct 方法

  • 方法和函数类似:fn 关键字、名称、参数、返回值
  • 方法与函数不同之处:
    • 方法是在struct(或 enum、trait 对象)的上下文中定义
    • 第一个参数是self,表示方法被调用的struct实例

定义方法

#[derive(Debug)]
struct Rectangle {
    width: u32,
    length: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.length
    }
}    

fn main() {
    let rect = Rectangle {
        width: 30,
        length: 50,
    };

    println!("{}", rect.area());

    println!("{:?}", rect);
    println!("{:#?}", rect);
}
  • 在 impl 块里定义方法
  • 方法的第一个参数可以是 &self,也可以获得其所有权或可变借用。和其他参数一样。
  • 更良好的代码组织。

方法调用的运算符

  • C/C++:ogject->something()(*object).something() 一样
  • Rust没有 -> 运算符
  • Rust会自动引用或解引用
    • 在调用方法时就会发生这种行为
  • 在调用方法时,Rust根据情况自动添加&、&mut或*,以便object可以匹配方法的签名
  • 下面两行代码效果相同:
    • p1.distance(&p2);
    • (&p1).distance(&p2);

方法参数

  • 方法可以由多个参数
#[derive(Debug)]
struct Rectangle {
    width: u32,
    length: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.length
    }

    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.length > other.length
    }
}    

fn main() {
    let rect = Rectangle {
        width: 30,
        length: 50,
    };

    let rect1 = Rectangle {
        width: 30,
        length: 50,
    };

    let rect2 = Rectangle {
        width: 10,
        length: 40,
    };

    let rect3 = Rectangle {
        width: 35,
        length: 55,
    };

    println!("{}", rect1.can_hold(&rect2));
    println!("{}", rect1.can_hold(&rect3));

    println!("{}", rect.area());

    println!("{:?}", rect);
    println!("{:#?}", rect);
}

// fn area(rect: &Rectangle) -> u32 {
//     rect.width * rect.length
// }

关联函数

  • 可以在 impl 块里定义不把self作为第一个参数的函数,它们叫关联函数(不是方法)
    • 例如:String::from()
  • 关联函数通常用于构造器(被关联类型的实例)
#[derive(Debug)]
struct Rectangle {
    width: u32,
    length: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.length
    }

    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.length > other.length
    }

    fn square(size: u32) -> Rectangle {
        Rectangle { width: size, length: size }
    }
}    

fn main() {
    let s = Rectangle::square(20);
    let rect = Rectangle {
        width: 30,
        length: 50,
    };

    let rect1 = Rectangle {
        width: 30,
        length: 50,
    };

    let rect2 = Rectangle {
        width: 10,
        length: 40,
    };

    let rect3 = Rectangle {
        width: 35,
        length: 55,
    };

    println!("{}", rect1.can_hold(&rect2));
    println!("{}", rect1.can_hold(&rect3));

    println!("{}", rect.area());

    println!("{:?}", rect);
    println!("{:#?}", rect);

    println!("{:?}", s)
}
  • :: 符号
    • 关联函数
    • 模块创建的命名空间

多个 impl 块

  • 每个struct允许拥有多个impl块

总结

Rust 的 Struct 是编程中的优雅利器,让你轻松组织数据、优化代码结构。通过本文,你学会了如何定义和实例化 Struct,使用方法和关联函数实现功能扩展,以及通过更新语法和调试技巧提升开发效率。从简单的长方形面积计算到复杂的数据管理,Struct 让 Rust 代码更清晰、更高效。无论你是刚入门 Rust 的新手,还是追求极致代码质量的开发者,掌握 Struct 都将为你的编程之旅增添无限可能!快动手实践,留言分享你的 Struct 代码吧!关注我们,解锁更多 Rust 编程干货!

参考

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论