rust程序设计语言 介绍了关于rust的方方面面, 我跟着学了两遍,中间隔了差不多一年,每次都是从零开始入门, 最近两个月用rust实际开发了个应用,才算真的入门. 这里记录下使用中的一些体验.
1 关于rust本身
数据类型,流程控制都很基本,crate和包封装也是基础.
1.1 所有权
所有权很重要, 开发中经常碰到的就是所有权问题, 特别是用到异步和多线程的时候; 当然这也是rust保证程序正确的一个很重要的手段, 一开始不太适应, 要逼着自己思考和组织数据, 熟悉了之后就好了.另外所有权问题涉及到切片Slice
, 主要用在传参和字符串, 需要掌握和熟练使用.
1.2 枚举
rust的枚举相比c++有个很大的特点是可以包含更多内容, 方便组织数据. Option
和Result
是rust中广泛使用的枚举类型. 枚举常常和模式匹配配合使用, 使rust的程序逻辑在编译阶段就尽量保证穷举所有情况.
1.3 字符串
要记得rust的字符串是用utf8存储的, 要区分开String
, &str
, [u8]
这些数据类型.
1.4 错误处理
很重要, 如果没有特别的需求,可以不用自己定义错误类型, 但经常要在函数调用的时候传递错误, 建议了解和使用anyhow
这个crate,方便错误传递.如果要自己定义,建议使用thiserror
.
1.5 泛型,trait
泛型要了解, 重要的是trait
, 有时候这两个会弄混–学的时候不会,用的时候就模糊了. 泛型是编译时分发, trait
算是动态分发.另外用到第三方库的时候, 也有很多接口是用trait
给出的, 看接口文档的时候要记得看看实现了哪些trait
.
1.6 生命周期
第一个应用程序可以不用自己写生命周期, 完全依赖复制和借用就行. 但也要了解一下.
1.7 迭代器和闭包
迭代器很多方法定义在Iterator
这个trait中, 建议浏览一遍,很多有用的. 闭包要掌握, 很多地方都会用到.
1.8 多线程和异步
我是直接用了tokio
, 会同时涉及到多线程和异步, 实现异步运行时依赖的async/await
,Future
,Waker
这些可以先不管, 先了解tokio
几个基本概念和select
的用法, 多运行多调试多重构, 这是个麻烦的过程,但是必经之路.
2 第三方库
lib.rs是第三方库集合,但这里很多,有时候也不知道到底要找哪个. 这里列一下用到的一些第三方库.
2.1 tokio
rust的异步运行时. rust语言本身只提供了async/await
支持, 标准库提供了Future
用于实现运行时的统一接口, tokio
则提供了异步运行时本身和最终的用户接口. 网络程序的话,建议直接学tokio
, 绕不开的.
里边很重要的是tokio::sync::Mutex
和std::sync::Mutex
的区别, tokio::sync::{mpsc, oneshot, broadcast}
几个通道的使用, select
的使用(这个相当重要).
2.2 clap
命令行解析库.
2.3 tracing
配合tokio
的日志库. clia-tracing-config
是个方便的工具库, 用于方便初始化tracing
日志库.
2.4 serde, toml, serde_json
serde
是序列化接口, toml
用于解析配置文件, serde_json
用于json操作.
2.5 rdkafka
kafka的rust接口.
2.6 prost, prost-build
protobuf
的rust接口. prost-build
用于在编译之前从.proto
文件生成.rs
数据接口.
2.7 bytes
方便操作二进制数据的库, 最开始用过deku
, 但deku
的问题是还不够灵活,特别是处理字段间关联会很麻烦. 还不如自己用bytes
直接操作这段内存.
2.8 hex
主要用于打印二进制数据, hex::encode()
将字节编码成十六进制字符串, hex::decode()
从十六进制字符串解码出原始字节.
2.9 chrono
方便的 时间格式化工具.
2.10 sqlx
支持mysql
, sqlite
, postgres
连接池, 支持tokio
异步.
2.11 redis
支持redis异步.
2.12 axum
方便集成web api, 支持异步.
2.13 scopeguard
提供defer!
, 用于异步时的范围资源清理.
2.14 anyhow, thiserror
前者用于错误传递,后者用于自定义错误.
2.15 criterion
替换cargo提供的性能测试框架.
3 总结
rust在保证大部分场景是安全高效的情况下,会把一些怪异的情况堆积到角落,比如Pin, unsafe
这些, 进而出现很复杂的语法,才能安抚编译器, 但对我的第一个应用来说, 没有(直接)使用这些东西也完成正常功能了.
用完rust,最大的感觉是安心, 很少运行时错误,大部分在编译阶段就被发现,或者被语言本身的机制所规避. 单元测试框架也很方便, 重构后也比c++更有信心, 总之心智负担小, 算是快爬到**”愚昧之巅”**了.