Rust实践总结
1. 语法
1.1. Rust中的r#""#
字符串字面值开头的r
不是一个操作符,而是一个前缀。
在普通的字符串文字中,需要对某些字符进行转义才能使它们成为字符串的一部分,例如"
和\
:
- 需要对
"
字符进行转义,否则它将终止字符串 - 需要对
\
进行转义,因为它是转义字符
在Rust中,如果字符串中有需要转义的字符,可以在字符串前面加r
前缀,然后放置任意数量的#
符号,再用左引号"
开始一个字符串。在结束该字符串时,再在右引号"
之后放置与开头相同数量的#
字符。这样,在""
之间的字符串中就可以放置原始字符串,而不需要进行任何转义。例如:
1 | r##"foo #"# bar"## |
表示字符串foo #"# bar
。
字符串不会在中间的引号处停止,因为它后面只有一个#
,而字符串是以两个#
开始的。
1.2. ?
运算符
参考 错误处理(Error Handling) 中 “2.4. 传播错误的简写:?运算符” 部分。
例:
1 | use std::fs::File; |
?
作用于Result
类型:- 结尾调用
?
,如果结果是Ok
,会返回Ok
中的值 - 如果结果是
Err
,?
会提早return,并返回Err
中的值
- 结尾调用
?
作用于Option
类型:- 如果值是
Some
,Some
中的值作为表达式的返回值,同时函数继续 - 如果值是
None
,None
会从函数中提前返回
- 如果值是
?
只能被用于函数的返回值与它作用的值相兼容的函数- 例如,上例中
?
作用于File::open("hello.txt")
的返回值,即Result
,那么整个函数的返回值类型也必须是Result
才可以
- 例如,上例中
2. Crates使用
2.1. serde
2.1.1. serde介绍
Rust中有一个99%的程序员或许都会用到的组件,那就是序列化组件: serde。
众所周知,rust是静态语言,这让我们在序列化上繁琐了很多,但是serde能帮助我们更好地序列化结构体,生产对应的数据。它实现了各种声明宏(declarative macros)以及过程宏(procedural macros)来协助我们序列化。
serde是Rust语言用来序列化和反序列化数据的一个非常高效的解决方案。本质上,serde提供了一个序列化层的概念。可以将任何支持的数据格式反序列化成中间格式,然后序列化成任何一种支持的数据格式。
同其他语言通过反射来实现序列化方案不同,serde基于Rust的trait系统来实现自己的序列化,每种数据结构通过实现serde的Serialize和Deserialize接口来实现序列化功能,这种实现方案可以有效避免反射的性能开销。Rust编译器可以在很多场景下对序列化进行高度优化,甚至可以达到一个资深工程师手写序列化代码的性能。
目前围绕serde支持的序列化的数据格式组件有:
- JSON,许多HTTP API都使用的JavaScript对象符号。
- Bincode,一个紧凑的二进制格式,用于伺服渲染的IPC引擎。
- CBOR,一种简洁的二进制对象表示,专为小消息大小设计而不需要版本协商。
- YAML,一个自称对人类友好的配置语言,其实不是标记语言。
- MessagePack,一个高效的二进制格式,类似于一个紧凑的JSON。
- TOML, Cargo使用的最小配置格式。
- Pickle, Python世界中常见的格式。
- RON,一个生锈的符号。
- BSON, MongoDB使用的数据存储和网络传输格式。
- Avro,在Apache Hadoop中使用的二进制格式,支持schema定义。
- JSON5,一个JSON的超集,包括一些来自ES5的产品。
- URL查询字符串,格式为
x-www-form-urlencoded
。 - Envy,一种将环境变量反序列化为锈蚀结构的方法。
- Envy Store
反序列化:
- Envy Store,一种反序列化AWS Parameter Store参数到Rust的方法结构体。(反序列化)
- S-expressions, Lisp使用的代码和数据的文本表示形式语言的家庭。
- D-Bus的二进制线格式。
- FlexBuffers,谷歌的FlatBuffers 0 -copy的无模式表兄弟序列化格式。
- Bencode,在BitTorrent协议中使用的一个简单的二进制格式。
- DynamoDB Items, rusoto_dynamodb用来传输数据的格式和DynamoDB。
- Hjson,一个JSON的语法扩展,围绕人类阅读和编辑而设计。(反序列化)
2.1.2. 使用derive
(Serialize 和 Deserialize)
为了方便实现你自己创建的数据结构的序列化功能,serde提供了一个derive macro来自动生成你的数据结构的Serialize
和Deserialize
trait的实现代码,让你定义的数据结构通过serde数据模型方便的表达出来。
你只需要在你代码里通过添加一行
1 |
serde就会自动生成这些实现代码。
此功能基于rust的#[derive]
范式来实现,类似于你通过derive自动实现系统内置的Clone
,Copy
,Debug
和其他的一些trait。它能够给绝大多数数据结构和枚举自动生成trait实现代码。极少数情况下,面对一些非常复杂的数据结构,你可能需要手工去实现这些代码。
2.1.3. #[derive(Serialize, Deserialize)]
使用示例
Cargo.toml
文件:
1 | [package] |
src/main.rust
文件:
1 | use serde::{Serialize, Deserialize}; |
cargo run运行结果:
2.1.4. #[serde(default)]
#[serde(default)]
用来设置字段的默认值。
示例:
1 | use serde::Deserialize; |
运行结果:
对r#""#
的说明见 Rust中的r#””# 部分。
2.2. config
GitHub链接:https://github.com/mehcode/config-rs
可用于从toml
、json
、yaml
、ini
等格式的文件中读取数据。示例:https://github.com/mehcode/config-rs/tree/master/examples
1 | use config::Config; |
Settings.toml
内容:
1 | debug = false |
Cargo.toml
内容:
1 | [package] |
目录结构:
1 | try_config |
cargo run
的运行结果:
参考链接
[1] serde - rust的序列化方案:https://zhuanlan.zhihu.com/p/54004232
[2] 【rust】序列化框架serde:https://whiteccinn.github.io/2021/04/13/Rust语言/rust-序列化框架serde/
[3] Using derive:https://serde.rs/derive.html
[4] Default value for a field:https://serde.rs/attr-default.html
[5] Rust中的r#””#:https://cloud.tencent.com/developer/ask/sof/37840