从 Option 类型说起

news/2025/1/12 19:52:05/

Option 不是结构体声明,而是枚举类型。印象中的枚举类型都是固定的常量,这里 Rust 的枚举支持了泛型。枚举了两种可能:有值、或没值。None表示没有值,Some(T) 表示存在 T 类型的值。

enum Option<T> {Some(T),None,
}

简单示例

使用一个简单的函数来体会一下 Option 的用法:返回变量 a 和 b 中最小的那个值,如果两者相等,返回 None。

fn min(a: u32, b: u32) -> Option<u32> {if a > b {return Some(b);}if a < b {return Some(a);}None
}

Rust 支持单测的能力,我们在函数的声明后追加单测用例。这个#[test]属于属性标记,Rust 中有各种各样的属性标记,后续会专门介绍。同 Go 一样,cargo build 的时候同样会忽略单测的方法。

#[test]
fn test_min() {assert_eq!(min(12u32, 10u32), Some(10u32));
}

包裹 tuple 类型

我们尝试使用 Option 返回一个 tuple 类型,tuple 也被叫做元组,用一个括号表示,由2个、3个…各种类型的值组成。Go 中没有这种类型,之所以提到这个类型,是想带着大家去考虑一下这种情景:如果返回值是包含 2 个值的 tuple 类型,我们应该使用 Option 还是应该使用 Option<(T,T)>?

我们给 (T, T) 来设定一个业务场景,表示一个点位数据:经度和纬度。多个点可以组成一条线,点和点之间使用分号分隔,点内部使用逗号分隔。我们构造一个简单的字符串:“116.42,39.89
;116.46,38.68”,先用一个更简单的例子来看一下:

fn parse_loc<T: FromStr>(s: &str, separator: char) -> Option<(T, T)> {match s.find(separator) {None => None, Some(index) => match (T::from_str(&s[..index]), T::from_str(&s[index+1..])) {(Ok(lng), Ok(lat)) => Some((lng, lat)),_ => None,}}
}#[test] 
fn test_parse_loc() { assert_eq!(parse_loc::<f64>("116.42,39.89", ','), Some((116.42, 39.89)))
}

如果将 Option<(T, T)> 修改成 Option,编译时不能通过的:mismatched types expected type parameter T found tuple (T, T)。由此可见,T 和 Go 语言中的 interface 或者泛型还是有区别的,Rust 也省去了后续类型断言的工作。

绑定关系

我们对 parse_loc 方法体中 <T: FromStr> 声明有些模陌生,FromStr 类似于 Go 语言中接口的声明,也定义了一组行为,约束类型 T 必须实现这样的行为。只不多 rust 中通过 trait 关键字来声明来实现。我们看官方文档对 FromStr 的解释:

pub trait FromStr: Sized {type Err;// Required methodfn from_str(s: &str) -> Result<Self, Self::Err>;
}

Result<>也属于泛型枚举类型,听到枚举类型,总觉得和印象中的枚举有些出入,rust 的枚举类型设计的过于丰富了。而解析就得用到 match 匹配模式。有点类似正则表达式 ,match 后面实际产生的值,要和 match 列举的模式相匹配,个数、类型都要一一对应。模式 _ 表示通配符,能匹配到任意值,但不会保存匹配到的结构。

总之,match 虽然是新的表达式,但还是比较容易理解的。

Self 关键字

我们继续看 FromStr 中声明的 Self 关键字,第一次接触也会困惑,其实还有 self 关键字,挺神奇的吧。Self 表示类型本身,比如 test_parse_loc 单测方法中,传递的 T 类型是 f64,那 Self 表示的就是 f64 类型。

我们扩展一个例子,来认识一下 self 关键字,通过 self 关键字来继续引申 Self 关键字。我们使用 rust 定义一个点类型结构体,如果结构体或者其中的字段要想在模块外部可见,需要在定义中加上 pub 关键字,默认都是私有属性。反观 go 语言,通过首字母大小写来控制访问权限,比 rust 要简洁不少。

pub struct Point {pub x: f64,pub y: f64
}

和 go 给结构体绑定方法一样,rust 也支持给结构体实现方法,我们现在给 Point 绑定一个方法,用来计算两个点之间的距离。hypot 方法是 f64 类型已经实现的,用来计算两个点之间的距离。

impl Point {pub fn distance(self, p: Point) -> f64 {(self.x - p.x).hypot(self.y - p.y)}
}

方法体中第一个参数 self 就是用来指代结构体本身,这又是 rust 专门声明的简写方式,帮助我们不需要特别声明 self 的类型。除了 self ,其实还有 &self 和 &mut self 的声明方式。我们在后续的文章中进行解释。

go 语言底层也做了这样的设计,方法的第一个参数是自己本身,只不过封装在了实现内部,降低了我们开发的负担。这么说来,感觉 go 确实好用。

我们继续说 Self 关键字,我们上面有提到 FromStr 的特性实现,类似 go 语言中的接口实现,我们也实现一个 rust 接口设计,同时,联动调整了 impl 语句,关键还是 for 表示 Point 类型实现了 Distance 特性。其实,distance 方法还可以添加默认的实现,这里也不展开。

在 trait Distance 中,我们使用 Self 来指代实现 Distance 的类型。说白了,就是 self 指代当前结构体,Self 指代当前结构体的类型。可能你已经敏锐的发现,Self 做了泛型要做的事情。

pub trait Distance {fn distance(self, p: Self) -> f64;
}impl Distance for Point {fn distance(self, p: Point) -> f64 {(self.x - p.x).hypot(self.y - p.y)}
}

Result

上面例子中,from_str 返回值类型为 Result,rust 给这个枚举类型提供了很多便捷的操作方法。


http://www.ppmy.cn/news/724248.html

相关文章

【云上服务器降低成本】

MD[云上服务器降低成本] 云上服务器降低成本 说明: 本文以华为云为例&#xff0c;主要讲解云上服务降低费用的使用技巧 1.ECS服务器降本 参考文档:华为云官网文档_迁移准备 1.1 ECS临时使用需求 1.项目初始阶段&#xff0c;需要进行大量试错运行&#xff0c;可以“按需”购…

PHY6222蓝牙5.2的SOC芯片可以兼容替代PHY6202和PHY6212

大家都很熟悉NORDIC的nRF52832是个非常优秀的作品&#xff0c;而作为替代nRF52832的一款产品&#xff0c;PHY6222也很可以啊 PHY6222是一款支持BLE 5.2功能和IEEE 802.15.4通信协议的系统级芯片&#xff08;SoC&#xff09;&#xff0c;集成了超低功耗的高性能多模射频收发机&…

HDU6222(acm2017-沈阳) 打表递推

题目链接&#xff1a; http://acm.hdu.edu.cn/showproblem.php?pid6222 题目大意: 寻找大于n的最小数t 使得t-1&#xff0c;t&#xff0c;t1这三个数构成的三角形为整数 n<10^30 思路&#xff1a; 看到n这么大&#xff0c;显然是瞎jiba找规律然后打表&#xff1f; 1…

PHY6222蓝牙5.2可替代NRF52832超低功耗SOC芯片

PHY6222是一款支持BLE 5.2功能和IEEE 802.15.4通信协议的系统级芯片&#xff08;SoC&#xff09;&#xff0c;集成了超低功耗的高性能多模射频收发机&#xff0c;搭载32-bit ARMCortex™-M0处理器&#xff0c;提供64K retention SRAM、可选128K-8M Flash、96KB ROM以及256bit e…

hdu 6222 Heron and His Triangle

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid6222 解析&#xff1a;规律&#xff1a;a[n] 4*a[n-1] - a[n-2] 代码&#xff1a; import java.io.*; import java.math.BigInteger; import java.util.*;public class Main {public static Scanner s new …

hi3798mv300是什么手机_四川移动魔百和M301H九联版-海思Hi3798MV300-6222B无

原标题&#xff1a;四川移动魔百和M301H九联版-海思Hi3798MV300-6222B无 四川移动魔百和M301H九联版-海思Hi3798MV300-6222B无线卡刷包 四川移动魔百和M301H九联版 ROM说明&#xff1a; 1.针对四川移动M301H-6222B无线短接卡刷固件&#xff0c;请对号入座&#xff1b;无线可正常…

佩尔方程以及hdu6222

背景介绍 佩尔方程&#xff0c;是一种不定二次方程。Pell方程&#xff0c;古希腊和印度的数学家对此类方程的研究做了最早的贡献&#xff0c;由费马首先进行了深入研究&#xff0c;拉格朗日给出了解决方案&#xff0c;但后此类方程来却被欧拉误记为佩尔提出&#xff0c;并写入…

BLE芯片PHY6222---两路PWM互补输出

文章目录 前言处理 前言 两路PWM驱动电机&#xff0c;一定情况下PHY6222存在复位且电机控制力度不足 两路PWM波形输出理应为异步&#xff0c;原因在于采用了定时不断开启&#xff0c;关闭&#xff0c;长时间运行会导致定时精度不准确&#xff0c;导致同一时间两路都输出高或者…