news 2026/7/23 18:47:57

【Rust自学】6.1. 定义枚举

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Rust自学】6.1. 定义枚举

6.1 定义枚举

6.1.1. 什么是枚举?

枚举允许我们通过列举所有可能的值来定义一个类型。这与其他编程语言中的枚举类似,但 Rust 的枚举更加灵活和强大,因为它们可以关联数据和方法,类似于其他语言中的类或结构体。

6.1.2. 定义枚举

举个例子,IP地址只有两种可能——IPv4和IPv6。它要么是IPv4,要么是IPv6,所以非常适合用枚举,因为枚举的值只能是其所有变体(枚举所有可能的值)中的一个。

enum IpAddrKind{ V4, V6, }

这段代码使用enum关键字声明了一个名为IpAddrKind的枚举类型,它有两个变体——V4V6——分别代表IPv4和IPv6。

6.1.3. 枚举值

创建枚举值非常简单,格式为枚举名::变体。例如:

let four = IpAddrKind::V4; let six = IpAddrKind::V6;

枚举的变体位于该枚举标识符的命名空间下,而这个标识符就是枚举类型的名字。

我们可以声明一个接收IpAddrKind作为参数的函数,传入的值既可以是V4也可以是V6

fn route(ip_addr: IpAddrKind) { match ip_addr { IpAddrKind::V4 => println!("IPv4"), IpAddrKind::V6 => println!("IPv6"), } }

让我们试试效果:
完整代码:

enum IpAddrKind{ V4, V6, } fn main() { let four = IpAddrKind::V4; let six = IpAddrKind::V6; // 调用函数 route(four); route(six); route(IpAddrKind::V4); } fn route(ip_addr: IpAddrKind) { match ip_addr { IpAddrKind::V4 => println!("IPv4"), IpAddrKind::V6 => println!("IPv6"), } }

输出:

IPv4 IPv6 IPv4

6.1.4. 将数据附加到枚举变体中

枚举是一种自定义数据类型,所以可以用作结构体字段的类型,例如:

struct IpAddr { kind: IpAddrKind, address: String, }

IpAddr中的kind字段类型是IpAddrKind,用于存储网络协议;另一个字段addressString类型,用于存储具体的IP地址。

通过这样的结构体,我们可以在main()函数中声明一些存储IPv4、IPv6信息的变量:

fn main() { let home = IpAddr { kind: IpAddrKind::V4, address: String::from("127.0.0.1"), }; let loopback = IpAddr { kind: IpAddrKind::V6, address: String::from("::1"), }; }

Rust允许把数据直接附加到枚举变体上,例如:

enum IpAddr { V4(String), V6(String), }

在每个变体后面加上一个类型(不必是同一种类型)。这里V4V6后面都跟了String类型。

这种做法的优点是:
- 不需要额外使用结构体
- 每个变体可以有不同的类型,以及不同数量的关联数据

例如:

enum IpAddr { V4(u8, u8, u8, u8), V6(String), }

IPv4实际上由四个8位数字组成(也就是四个能装进u8的值),而IPv6是字符串,所以应使用String。如果我们想把V4地址存成四个u8值,同时仍把V6地址表示成String,就无法使用结构体。枚举可以轻松处理这种情况。

我们来重写一下前面的代码:

enum IpAddrKind{ V4(u8, u8, u8, u8), V6(String), } fn main() { let home = IpAddrKind::V4(127, 0, 0, 1); let loopback = IpAddrKind::V6(String::from("::1")); }

确实比前面的代码短多了。

6.1.5. 标准库中的IpAddr

事实上,标准库已经提供了表示IP地址的枚举。来看一下官方是怎么写的:

struct Ipv4Addr { // --snip-- } struct Ipv6Addr { // --snip-- } enum IpAddr { V4(Ipv4Addr), V6(Ipv6Addr), }

Ipv4AddrIpv6Addr的内容这里没有写出来,但这不是重点。重点是此代码说明任何类型的数据都可以放进枚举变体中:例如字符串、数字类型或结构体。甚至还可以包含另一个枚举。

6.1.6. 在枚举上使用方法(Method)

方法(Method)的概念在上一篇文章 5.3. struct的方法(Method) 中已经介绍过,这里不再过多展开。定义方法使用impl关键字,如下例:

enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), } impl Message { fn call(&self) { println!("Something happens"); } } fn main(){ let m = Message::Write(String::from("hello")); m.call(); }

该枚举有四种不同的变体:
-Quit:不携带任何数据。
-Move:包含一个匿名结构体。
-Write:包含一个String
-ChangeColor:包含三个i32值。

main中,变量m被声明为Message枚举的Write变体,并附带了Stringhello。然后在m上调用call方法,就会打印Something happens

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/23 18:46:27

【Rust自学】3.2. 数据类型:标量类型

3.2 数据类型:标量类型 3.2.0. 写在正文之前 欢迎来到Rust自学的第三章,一共有6个小节,分别是: - 变量与可变性 - 数据类型:标量类型(本文) - 数据类型:复合类型 - 函数和注释 - 控制流&#…

作者头像 李华
网站建设 2026/7/23 18:45:27

基于ddddocr与Hu矩的验证码识别技术实践

1. 项目背景与需求分析验证码识别一直是自动化测试和爬虫开发中的难点问题。某象验证码作为业内知名的验证码服务提供商,其差异点击验证码通过动态生成干扰元素和随机位置点击点,给传统OCR识别带来了巨大挑战。这类验证码通常包含以下特征:随…

作者头像 李华
网站建设 2026/7/23 18:41:45

工业5G专网切片架构与末端节点高EMC抗干扰设计实战指南

摘要:随着工信部等八部门联合印发《关于推动工业互联网高质量发展的实施意见》,建设5万张工业5G专网与培育5G分级工厂成为全行业最核心的技术演进议题。在极其复杂的强电磁、高反射、NLOS(非视距)工业现场,传统的无线数…

作者头像 李华
网站建设 2026/7/23 18:41:38

Hercules微控制器ECC安全机制:从原理到实战的嵌入式数据保护

1. 项目概述与核心价值在汽车电子、工业控制这些对可靠性要求近乎苛刻的领域,一个随机的比特翻转都可能导致灾难性后果。想象一下,一辆高速行驶的汽车,其发动机控制单元(ECU)因为宇宙射线或电磁干扰导致内存中一个关键…

作者头像 李华
网站建设 2026/7/23 18:40:28

GLM-5 DSA稀疏注意力技术解析与应用实践

1. GLM-5 DSA稀疏注意力技术核心解析 在2026年大模型技术迭代中,GLM-5采用的DSA(DeepSeek Sparse Attention)架构成为降低部署成本的关键突破。与传统密集注意力机制相比,该技术通过动态token筛选将计算复杂度从O(L)降至近似线性&…

作者头像 李华
网站建设 2026/7/23 18:39:40

基于YOLOv8的牙齿健康检测系统开发全流程

1. 项目概述:基于YOLOv8的牙齿健康检测系统这个开源项目提供了一个完整的牙齿健康状态检测解决方案,从数据集标注到模型训练再到Web前端展示的全套流程。系统采用当前最先进的YOLOv8目标检测算法,并针对牙齿检测任务进行了70项改进创新点优化…

作者头像 李华