├── README.md ├── Rust入门秘笈.pdf ├── 入门秘笈 ├── Rust Box.md ├── Rust Deref trait.md ├── Rust Drop trait.md ├── Rust Trait.md ├── Rust for回圈.md ├── Rust if in a let语句.md ├── Rust if let控制流程.md ├── Rust if语句.md ├── Rust loop回圈.md ├── Rust use关键字参照模组.md ├── Rust while回圈.md ├── Rust不可恢复的错误.md ├── Rust公开函式.md ├── Rust切片.md ├── Rust列举.md ├── Rust参照和借用.md ├── Rust可恢复的错误.md ├── Rust向量.md ├── Rust字串.md ├── Rust开发环境安装.md ├── Rust所有权.md ├── Rust智慧指标.md ├── Rust档案系统.md ├── Rust模组.md ├── Rust泛型.md ├── Rust生命周期.md ├── Rust的特点.md ├── Rust第一个程式.md ├── Rust简介.md ├── Rust结构体.md ├── Rust结构体方法语法.md ├── Rust结构体更新语法.md ├── Rust错误处理.md └── 匹配运算子.md └── 文章 ├── Rust 与 C++:深入的语言比较.md ├── 基于Rust的Android Native内存分析方案.md └── 理解 Rust 的生命周期.md /README.md: -------------------------------------------------------------------------------- 1 | # 🏄💨【最安全的编程语言】Rust工程师枕边资料,大牛文章,开源框架,官方文档,视频,推荐书籍,学习干货,大牛语录 2 | 3 |
4 | 5 | ![rust](https://user-images.githubusercontent.com/87457873/132184451-55f1125e-acad-4cc7-9e56-ecbffc0db412.png) 6 | 7 | ## 一个安全、并发、实用的系统语言 8 | 9 |
10 |
11 | 12 | [🏝
     环境搭建     ](https://github.com/0voice/Understanding_in_Rust#-%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA) |[📕
    入门秘笈    ](https://github.com/0voice/Understanding_in_Rust#-%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88-pdf%E6%A1%A3%E4%B8%8B%E8%BD%BD)| [📖
    推荐书籍    ](https://github.com/0voice/Understanding_in_Rust/blob/main/README.md#-%E6%8E%A8%E8%8D%90%E4%B9%A6%E7%B1%8D) 13 | :-------: | :-------: | :---------: 14 | **[📑
精选文章](https://github.com/0voice/Understanding_in_Rust#-%E5%A4%A7%E7%89%9B%E6%96%87%E7%AB%A0)** | **[📰
官方文档](https://github.com/0voice/Understanding_in_Rust/blob/main/README.md#-%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3)**| **[✈
杂货铺](https://github.com/0voice/Understanding_in_Rust/blob/main/README.md#-%E6%9D%82%E8%B4%A7%E9%93%BA)** 15 | **[💽
视频](https://github.com/0voice/Understanding_in_Rust#-%E8%A7%86%E9%A2%91)** | **[🏗
开源框架](https://github.com/0voice/Understanding_in_Rust#-%E5%BC%80%E6%BA%90%E6%A1%86%E6%9E%B6)** | **[🐂
大牛语录](https://github.com/0voice/Understanding_in_Rust/blob/main/README.md#-%E5%A4%A7%E7%89%9B%E8%AF%AD%E5%BD%95)** 16 | 17 |
18 |
19 | 20 |
21 | 22 | 23 | 24 | 25 | # 🤔 Why Rust?Why can? 26 | 27 | ### Jay Oster, PubNub 架构师 : 28 | 29 | “除了安全和性能,我们还有: 30 | 31 | - 泛型; 32 | - 特征; 33 | - 代数类型; 34 | - 函数式和命令式范式; 35 | - 可能是世界上最好的依赖管理和构建工具,实际上解决了‘依赖地狱’问题; 36 | - 对内嵌文档、测试和性能评测的美妙支持; 37 | - 一个大的且正在生长的库、抽象、工具生态; 38 | - 过程宏; 39 | - 与已有代码的 FFI 交互性; 40 | - 支持一打平台(更多的在路上!); 41 | - 对开发者体验是正向的、毋庸置疑的满足。 42 | 43 | Rust 是唯一一个下面所有框框都打勾的语言: 44 | 45 | - 内存安全 46 | - 类型安全 47 | - 消除数据竞争 48 | - 使用前编译 49 | - 建立(并且鼓励)在零抽象之上 50 | - 最小的运行时(无停止世界的垃圾搜集器,无 JIT 编译器,无 VM) 51 | - 低内存占用(程序可以运行在资源受限的环境,比如小的微控制器) 52 | - 裸金属目标(比如,写一个 OS 内核或者设备驱动,把 Rust 当一个 ‘高层’汇编器使用)” 53 | 54 | ### Peter Varo: 55 | 56 | “Rust 有一个很香的地方:它像 C 和 C++ 那样底层,因此也具有底层的这些优势(比如,控制、大小、速度等)。同时呢,它又像 Haskell 那样高层,自带令人吃惊的大量功能传承。它还是命令式的,所以容易被大多数人上手。然后它又像 Python 一样灵活,比如,' 鸭子类型(duck-typing)' 的概念出现在编译时(比如,特征限定),然后它又没有陈旧的面向对象模型以及由这个模型导致的各种出名的问题。 57 | 58 | 最后但很重要的是,还有一连串的东西被包含进来:精简短小的语法,语言提供的数目不多的特性,标准库及其一致性,高质量的文档的集成,包括对初学者和高级用户都适用的学习材料,这些都是促成因素。” 59 | 60 | # 🏝 环境搭建 61 | 62 | **安装及工具:https://www.rust-lang.org/zh-CN/learn/get-started** 63 | 64 | # 📕 入门秘笈 [(PDF档下载)](https://github.com/0voice/Understanding_in_Rust/blob/main/Rust%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88.pdf) 65 | 66 | - [Rust简介](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E7%AE%80%E4%BB%8B.md)
67 | - [Rust的特点](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E7%9A%84%E7%89%B9%E7%82%B9.md)
68 | - [Rust开发环境安装](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E5%AE%89%E8%A3%85.md)
69 | - [Rust第一个程式](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E7%AC%AC%E4%B8%80%E4%B8%AA%E7%A8%8B%E5%BC%8F.md)
70 | - [Rust if语句](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%20if%E8%AF%AD%E5%8F%A5.md)
71 | - [Rust if in a let语句](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%20if%20in%20a%20let%E8%AF%AD%E5%8F%A5.md)
72 | - [Rust loop回圈](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%20loop%E5%9B%9E%E5%9C%88.md)
73 | - [Rust for回圈](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%20for%E5%9B%9E%E5%9C%88.md)
74 | - [Rust while回圈](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%20while%E5%9B%9E%E5%9C%88.md)
75 | - [Rust所有权](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E6%89%80%E6%9C%89%E6%9D%83.md)
76 | - [Rust参照和借用](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E5%8F%82%E7%85%A7%E5%92%8C%E5%80%9F%E7%94%A8.md)
77 | - [Rust切片](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E5%88%87%E7%89%87.md)
78 | - [Rust结构体](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E7%BB%93%E6%9E%84%E4%BD%93.md)
79 | - [Rust结构体更新语法](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E7%BB%93%E6%9E%84%E4%BD%93%E6%9B%B4%E6%96%B0%E8%AF%AD%E6%B3%95.md)
80 | - [Rust结构体方法语法](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E7%BB%93%E6%9E%84%E4%BD%93%E6%96%B9%E6%B3%95%E8%AF%AD%E6%B3%95.md)
81 | - [Rust列举](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E5%88%97%E4%B8%BE.md)
82 | - [匹配运算子](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/%E5%8C%B9%E9%85%8D%E8%BF%90%E7%AE%97%E5%AD%90.md)
83 | - [Rust if let控制流程](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%20if%20let%E6%8E%A7%E5%88%B6%E6%B5%81%E7%A8%8B.md)
84 | - [Rust模组](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E6%A8%A1%E7%BB%84.md)
85 | - [Rust档案系统](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E6%A1%A3%E6%A1%88%E7%B3%BB%E7%BB%9F.md)
86 | - [Rust公开函式](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E5%85%AC%E5%BC%80%E5%87%BD%E5%BC%8F.md)
87 | - [Rust use关键字参照模组](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%20use%E5%85%B3%E9%94%AE%E5%AD%97%E5%8F%82%E7%85%A7%E6%A8%A1%E7%BB%84.md)
88 | - [Rust向量](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E5%90%91%E9%87%8F.md)
89 | - [Rust字串](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E5%AD%97%E4%B8%B2.md)
90 | - [Rust错误处理](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86.md) 91 | - [Rust不可恢复的错误](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E4%B8%8D%E5%8F%AF%E6%81%A2%E5%A4%8D%E7%9A%84%E9%94%99%E8%AF%AF.md)
92 | - [Rust可恢复的错误](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E5%8F%AF%E6%81%A2%E5%A4%8D%E7%9A%84%E9%94%99%E8%AF%AF.md)
93 | - [Rust泛型](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E6%B3%9B%E5%9E%8B.md)
94 | - [Rust Trait](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%20Trait.md)
95 | - [Rust生命周期](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.md)
96 | - [Rust智慧指标](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%E6%99%BA%E6%85%A7%E6%8C%87%E6%A0%87.md)
97 | - [Rust Box](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%20Box%3CT%3E.md)
98 | - [Rust Deref trait](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%20Deref%20trait.md)
99 | - [Rust Drop trait](https://github.com/0voice/Understanding_in_Rust/blob/main/%E5%85%A5%E9%97%A8%E7%A7%98%E7%AC%88/Rust%20Drop%20trait.md)
100 | 101 | # 📖 推荐书籍 102 | 103 | ### 国内书籍 104 | 105 | - [《深入浅出Rust》](https://jp1lib.org/s/?q=%E3%80%8A%E6%B7%B1%E5%85%A5%E6%B5%85%E5%87%BARust%E3%80%8B) 106 | 107 | - [《Rust权威指南》](https://book.douban.com/subject/35081743/) 108 | 109 | - [《Rust 程序设计语言》](https://kaisery.github.io/trpl-zh-cn/) 110 | 111 | - [《精通Rust(第2版)》](https://jp1lib.org/book/17127064/820864) 112 | 113 | ### 国外书籍 114 | 115 | **入门书籍** 116 | 117 | - [《The Rust Programming Language》](https://doc.rust-lang.org/book/) 118 | 119 | 欢迎!本书将教你有关 Rust 编程语言的知识。Rust 是一种系统编程语言,专注于三个目标:安全性、速度和并发性。它在没有垃圾收集器的情况下实现了这些目标,使其成为其他语言不擅长的许多用例的有用语言:嵌入其他语言、具有特定空间和时间要求的程序以及编写低级代码,例如设备驱动程序和操作系统。它通过在不产生运行时开销的情况下进行大量编译时安全检查,同时消除所有数据竞争,从而改进了针对此空间的当前语言。Rust 还旨在实现“零成本抽象”,尽管其中一些抽象感觉像是高级语言的抽象。即便如此,Rust 仍然允许像低级语言一样进行精确控制。 120 | 121 | - [《Welcome to Rust-101》](https://www.ralfj.de/projects/rust-101/main.html) 122 | 123 | 这是 Rust-101,一个 Rust 语言的小教程。它旨在成为一门交互式的动手课程:我相信真正学习一门语言的唯一方法是在其中编写代码,因此您应该在课程中进行编码。如果您有任何未在此处回答的问题,请查看下面的“其他资源”。尤其是,IRC 频道里挤满了愿意帮助你的很棒的人!我在那里花了很多时间 ;-) 我假设对编程有一定的了解,因此不会解释大多数语言共有的基本概念。相反,我将专注于 Rust 的特殊之处。 124 | 125 | - [《Rust by Example》](http://rustbyexample.com/) 126 | 127 | Rust by Example (RBE) 是一组可运行的示例,用于说明各种 Rust 概念和标准库。 128 | 129 | - [《Why Rust?》](https://kr1lib.org/book/10990507/3a18af) 130 | 131 | 尽管自 40 多年前引入 C 以来,系统编程语言已经有了很大的发展,但我们对造成巨大后果的愚蠢错误的能力仍然没有改变,新闻中经常有生动的例子。这份 O'Reilly 报告研究了 Rust,这是一种新的系统编程语言,它将安全性和安全性与性能相结合,与 C 和 C++ 相当。 132 | 133 | - [《Learning Rust》](https://kr1lib.org/book/11689651/08c0b6) 134 | 135 | Rust 是一种高度并发和高性能的语言,专注于安全和速度、内存管理和编写干净的代码。它还保证线程安全,其目的是提高现有应用程序的性能。它得到了 Mozilla 的支持,以解决并发的关键问题。 136 | 137 | - [《Beginning Rust - From Novice to Professional》](https://kr1lib.org/book/3490555/7b7c82) 138 | 139 | 学习在 Unix、Linux shell、macOS 和 Windows 命令行上以简单、循序渐进的方式使用 Rust 进行编程。当您阅读本书时,您将建立在您在前几章中获得的知识的基础上,并了解 Rust 提供了什么。 140 | 141 | 开始 Rust 从 Rust 的基础开始,包括如何命名对象、控制执行流和处理原始类型。您将看到如何进行算术运算、分配内存、使用迭代器以及处理输入/输出。一旦掌握了这些核心技能,您将着手处理错误并使用 Rust 的面向对象特性立即构建健壮的 Rust 应用程序。 142 | 143 | 只需要基本的编程知识,最好是 C 或 C++。要理解这本书,知道什么是整数和浮点数,以及区分标识符和字符串文字就足够了。 144 | 145 | - [《Rust Cookbook》](https://kr1lib.org/book/3362654/66eb5a) 146 | 147 | 本书将帮助您理解 Rust 语言的核心概念,使您能够通过整合零成本抽象和更好的内存管理等功能来开发高效和高性能的应用程序。深入研究 Rust 中的高级概念,例如错误处理、宏、包和并行性。在本书的最后,学习如何创建 HTTP 服务器和 Web 服务,在服务器端编程方面建立强大的基础知识,并能够提供使用 Rust 构建高性能和更安全的生产级 Web 应用程序和服务的解决方案。 148 | 149 | - [《Rust Standard Library Cookbook》](https://kr1lib.org/book/3571952/9b9cdb) 150 | 151 | Mozilla 的 Rust 以其惊人的功能和强大的库而备受关注。本书将带您了解各种秘诀,教您如何利用标准库来实现高效的解决方案。 152 | 153 | 本书首先简要介绍了标准库和馆藏的基本模块。从这里开始,食谱将涵盖通过解析支持文件/目录处理和交互的包。您将了解与高级数据结构、错误处理和网络相关的包。您还将学习使用期货和实验性夜间功能。这本书还涵盖了 Rust 中最相关的外部 crate。 154 | 155 | - [《Network Programming with Rust》](https://kr1lib.org/book/3571947/48c564) 156 | 157 | Rust 足够低级,可以提供对内存的细粒度控制,同时通过编译时验证提供安全性。这使得它特别适合编写低级网络应用程序。 158 | 159 | 本书分为三个主要部分,将带您踏上构建功能齐全的 Web 服务器的激动人心的旅程。本书首先对 Rust 和基本的网络概念进行了扎实的介绍。这将为整本书奠定基础并定下基调。在第二部分中,我们将深入研究如何使用 Rust 开发网络软件。从使用套接字的客户端-服务器网络到 IPv4/v6、DNS、TCP、UDP,您还将了解使用 serde 序列化和反序列化数据。这本书展示了如何通过 HTTP 与 REST 服务器进行通信。本书的最后一部分讨论了使用 Tokio 堆栈进行异步网络编程。鉴于安全对于现代系统的重要性,您将看到 Rust 如何支持常见的原语,例如 TLS 和公钥加密。 160 | 161 | - [《Rust Programming by Example》](https://kr1lib.org/book/5669466/ef3a67) 162 | 163 | 从介绍 Rust 开始,您将学习基本方面,例如其语法、数据类型、函数、泛型、控制流等。在此之后,您将直接开始构建您的第一个项目,俄罗斯方块游戏。接下来,您将使用 Tokio(可扩展且高效的异步 IO Rust 库)构建图形音乐播放器并使用快速、可靠的网络软件。 164 | 165 | 在本书的过程中,您将探索 Rust 编程的各种特性,包括它的 SDL 特性、事件循环、文件 I/O 和著名的 GTK+ 小部件工具包。通过这些项目,您将看到 Rust 在并发方面的表现——包括并行性、可靠性、改进的性能、泛型、宏和线程安全。我们还将介绍 Rust 的一些异步和反应式编程方面。 166 | 167 | - [《Rust Quick Start Guide》](https://kr1lib.org/book/11689628/cf06fb) 168 | 169 | 熟悉使用流行的新系统编程语言编写程序,这些语言将低级语言的强大性能与多线程代码中的线程安全等高级功能结合在一起。 170 | 171 | - [《Rust in Action [MEAP]》](https://kr1lib.org/book/11235796/a7ef40) 172 | 173 | Rust in Action 是一本面向想要探索 Rust 编程语言世界的中级程序员的书。它适用于可能已经用尽网络上的免费资料但仍想了解更多信息的人。它与 Rust 编程的其他材料不同,因为它还教您有关系统编程的知识。您将能够更多地了解 CPU 的工作原理、计算机如何计时、指针是什么以及您的网卡和键盘如何告诉 CPU 它们已准备好读取输入。 174 | 175 | 从系统编程书籍的角度来看,它实际上也是独一无二的 - 因为几乎每个示例都适用于 Windows!如果你是那种喜欢实际例子的学习者,你会喜欢阅读这本书。 176 | 177 | - [《A Gentle Introduction to Rust》](https://stevedonovan.github.io/rust-gentle-intro/) 178 | 179 | Rust 是一种静态和强类型的系统编程语言。静态意味着所有类型在编译时都是已知的,强烈意味着这些类型旨在使编写不正确的程序变得更加困难。一个成功的编译意味着你可以比使用像 C 这样的牛仔语言更好地保证正确性。系统意味着生成最好的机器代码,并完全控制内存使用。因此,其用途非常核心:操作系统、设备驱动程序和甚至可能没有操作系统的嵌入式系统。然而,它实际上也是一种非常令人愉快的语言,可以用来编写普通的应用程序代码。 180 | 181 | 与 C 和 C++ 的最大区别在于 Rust 默认是安全的;检查所有内存访问。意外损坏内存是不可能的。 182 | 183 | - [《Practical Machine Learning with Rust: Creating Intelligent Applications in Rust》](https://kr1lib.org/book/5304256/0ff807) 184 | 185 | Rust 中的机器学习已经被社区忽视了很长一段时间。由于宇宙中散布着许多不同的板条箱,这本书试图统一所有的信息和用法,并在某种程度上动摇社区采取行动。数据是新的前沿领域,而 Rust 必须成为其中的一部分。 186 | 187 | 阅读了使用 Rust 的实用机器学习之后,您将对使用 Rust 创建高计算库有一个深入的了解。掌握了这种神奇语言的知识,您将能够创建性能更高、内存安全且资源占用更少的应用程序。 188 | 189 | - [《Rust Web Development》](https://kr1lib.org/book/11729741/a127f0) 190 | 191 | Rust Web Development 是使用 Rust 构建基于服务器的 Web 应用程序的实践指南。如果您使用 Java、C# 或 PHP 构建了 Web 服务器,您会立即爱上 Rust 提供的性能和开发体验。本书向您展示了如何使用纯 Rust 以及重要的 Rust 库(例如用于异步运行时的 tokio、用于 Web 服务器和 API 的 warp 以及运行外部 HTTP 请求的 reqwest 等)高效工作。 192 | 193 | 您可以将这本书交给新聘用的开发人员,并让他们使用这本书。它包含非常实用的示例和模式,并为未来探索该主题奠定了坚实的基础。 194 | 195 | **进阶书籍** 196 | 197 | - [《The Rustonomicon》](https://doc.rust-lang.org/nightly/nomicon/) 198 | 199 | 本书深入探讨了编写正确的不安全 Rust 程序所需的所有可怕细节。由于这个问题的性质,它可能会导致释放出无法言喻的恐怖,将你的心灵粉碎成十亿个无限小的绝望碎片。 200 | 201 | 如果您希望编写 Rust 程序的职业生涯长久而快乐,那么现在您应该回过头来忘记您曾经看过这本书。这不是必要的。但是,如果您打算编写不安全的代码——或者只是想深入了解语言的本质——这本书包含了宝贵的信息。 202 | 203 | - [《Programming Rust》](https://1lib.limited/book/3400043/791885) 204 | 205 | 这本实用的书向系统程序员介绍了 Rust,一种新的前沿语言。您将了解 Rust 如何提供静态验证的内存安全和低级控制的罕见且有价值的组合——想象一下 C++,但没有悬空指针、空指针取消引用、泄漏或缓冲区溢出。 206 | 207 | - [《Rust Essentials - Second Edition》](https://1lib.limited/book/3427870/81d715) 208 | 209 | 本书首先论证了 Rust 在当今编程语言领域的独特地位。安装 Rust 并学习如何使用它的包管理器 Cargo。逐步介绍各种概念:变量、类型、函数和控制结构,以打下基础。然后探索更多结构化数据,例如字符串、数组和枚举,并了解模式匹配的工作原理。 210 | 211 | 在这一切中,本书强调了 Rust 编译器用来生成安全代码的独特推理方式。接下来看看 Rust 特定的错误处理方式,以及特征在 Rust 代码中的整体重要性。在我们探索各种指针类型时,将深入探讨内存安全的支柱。接下来,看看宏如何简化代码生成,以及如何使用模块和板条箱组合更大的项目。最后,了解我们如何在 Rust 中编写安全的并发代码并与 C 程序接口,了解 Rust 生态系统,并探索标准库的使用。 212 | 213 | - [《Hands-On Concurrency with Rust》](https://1lib.limited/book/11689707/4154e1) 214 | 215 | 本书将教你如何在现代机器上管理程序性能,并在 Rust 中构建快速、内存安全和并发的软件。它从 Rust 的基础开始,讨论机器架构概念。您将了解如何系统地衡量和改进 Rust 代码的性能,以及如何自信地编写集合。您将了解应用于线程的 Sync 和 Send 特性,并使用锁、原子原语、数据并行等来协调线程执行。 216 | 217 | 本书将向您展示如何在 C++ 代码中有效地嵌入 Rust,并探索用于多线程应用程序的各种 crate 的功能。它深入探讨了实现。您将了解互斥锁的工作原理并自行构建多个互斥锁。您将掌握生态系统中存在的完全不同的方法来构建和管理大规模系统。 218 | 219 | - [《Hands-On Functional Programming in Rust》](https://1lib.limited/book/11689735/4d162e) 220 | 221 | 函数式编程允许开发人员将程序划分为更小的、可重用的组件,从整体上简化软件的创建、测试和维护。结合 Rust 的强大功能,您可以开发满足现代软件需求的强大且可扩展的应用程序。本书将帮助您发现可用于以功能方式构建软件的所有 Rust 功能。 222 | 223 | 我们首先对针对不同问题和模式的函数式方法和面向对象方法进行简要比较。然后我们快速查看控制流的模式、数据以及这些函数式编程独有的抽象。下一部分介绍如何在 Rust 中创建功能性应用程序;还讨论了 Rust 独有的可变性和所有权。接下来检查纯函数,您将掌握闭包、它们的各种类型和柯里化。我们还通过功能设计原则和使用宏的元编程来实现并发。最后,我们看看调试和优化的最佳实践。 224 | 225 | 读完本书,您将熟悉函数式编程方法,并能够在日常工作中使用这些技术。 226 | 227 | - [《Rust High Performance》](https://1lib.limited/book/11000538/3e9291) 228 | 229 | 有时,很难从 Rust 中获得最佳性能。这本书教你将你的 Rust 代码的速度优化到 C/C++ 等语言的水平。您将了解并修复常见的陷阱,了解如何通过使用元编程来提高生产力,并通过安全轻松地并发执行部分代码来加速代码。您将掌握这门语言的特性,这将使您脱颖而出,并使用它们来真正提高算法的效率 230 | 231 | 本书以一个温和的介绍开始,以帮助您识别 Rust 编程时的瓶颈。我们重点介绍了常见的性能缺陷,以及及早发现和解决这些问题的策略。我们继续掌握 Rust 的类型系统,这将使我们能够在编译时在性能和安全性方面进行令人印象深刻的优化。然后,您将学习如何在 Rust 中有效地管理内存,掌握借用检查器。我们继续测量性能,您将看到这如何影响您编写代码的方式。继续前进,您将在 Rust 中执行元编程,以提高代码的性能和生产力。您最终将学习 Rust 中的并行编程,它通过使用多线程和异步编程实现高效和更快的执行。 232 | 233 | - [《Zero To Production In Rust》](https://zero2prod.com/) 234 | 235 | 如果您想学习如何使用 Rust 进行后端开发,这里就是您的最佳选择。 236 | 237 | Rust 的采用率达到了历史最高水平:越来越多的公司正在尝试和招聘。
238 | 如果您对使用 Rust 构建 API 感兴趣,零到生产是您 Rust 之旅的理想起点。
239 | 您将边做边学:我们将从头开始,一步一步地构建一个功能齐全的电子邮件通讯后端 API。
240 | 241 | 您将学习: 242 | 243 | 1、导航和利用 Rust 的 crates 生态系统
244 | 2、构建您的应用程序以使其模块化和可扩展
245 | 3、编写测试,从单个单元到成熟的集成测试
246 | 4、使用类型系统为您的域建模以强制执行不变量
247 | 5、收集日志、跟踪和指标以观察应用程序的状态
248 | 6、为您的 Rust 项目设置一个强大的持续集成和持续部署管道
249 | 250 | - [《Programming WebAssembly with Rust》](https://1lib.limited/book/5001228/7b21a9) 251 | 252 | WebAssembly 不仅仅是一项革命性的新技术。它正在重塑我们为 Web 及其他领域构建应用程序的方式。在 ActiveX 和 Flash 等技术失败的地方,您现在可以使用您喜欢的任何语言编写代码并编译为 WebAssembly,以便在浏览器、移动设备、嵌入式设备等中运行的快速、类型安全的代码。将 WebAssembly 的便携、高性能模块与 Rust 的安全性和强大功能相结合,是一个完美的开发组合。 253 | 254 | 了解 WebAssembly 的堆栈机器架构如何工作,安装低级 wasm 工具,并发现编写原始废弃代码的黑暗艺术。在此基础上构建并学习如何通过实现跳棋游戏的逻辑从 Rust 编译 WebAssembly 模块。在 Rust 中创建 wasm 模块,以多种引人注目的方式与 JavaScript 进行互操作。将您的新技能应用于非网络主机的世界,并创建从在 Raspberry Pi 上运行的控制照明系统的应用程序到功能齐全的在线多人游戏引擎,开发人员可以上传他们自己的竞技场绑定 WebAssembly 战斗模块. 255 | 256 | 立即开始使用 WebAssembly,并改变您对 Web 的看法。 257 | 258 | - [《Step Ahead with Rust: Systems Programming in Rust》](https://www.armstrong-publications.com/product/step-ahead-with-rust-super-combo/) 259 | 260 | 从基本的编程模式到深入了解该语言,Step Ahead with Rust 旨在帮助您从编写程序到使用 Rust 构建软件。本书将向您展示 Rust 语言最重要的特性,包括货物、类型系统、迭代器等。读完本书,您应该会熟悉更多内容,并准备好处理其余的高级主题。 261 | 262 | 在您阅读本书的过程中,我们建议您花时间尝试一下书页中所呈现的内容。这本书都是关于 Rust 的实际应用,所以在实践中应用它是值得期待的。本书涵盖:货物、Rust 类型系统、迭代器、宏、所有权、借用和生命周期、不安全模式、并发。A Step Ahead with Rust 读者应该是一位经验丰富的开发人员,希望提高他们的 Rust 开发技能。 263 | 264 | - [《Creative Projects for Rust Programmers》](https://1lib.limited/book/5639719/c52aca) 265 | 266 | 了解 Rust 编程语言的最新特性、有用的库和框架的实用指南,将帮助您设计和开发有趣的项目 267 | 268 | 学习: 269 | 270 | 1、访问 TOML、JSON 和 XML 文件以及 SQLite、PostgreSQL 和 Redis 数据库
271 | 2、使用 JSON 有效负载开发 RESTful Web 服务
272 | 3、使用 HTML 模板和 JavaScript 创建 Web 应用程序,使用 WebAssembly 创建前端 Web 应用程序或 Web 游戏
273 | 4、构建桌面 2D 游戏
274 | 5、为编程语言开发解释器和编译器
275 | 6、创建机器语言模拟器
276 | 7、使用可加载模块扩展 Linux 内核
277 | 278 | # 📑 大牛文章 279 | 280 | - [理解 Rust 的生命周期](https://github.com/0voice/Understanding_in_Rust/blob/main/%E6%96%87%E7%AB%A0/%E7%90%86%E8%A7%A3%20Rust%20%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.md) 281 | - [高德技术 | 基于Rust的Android Native内存分析方案](https://github.com/0voice/Understanding_in_Rust/blob/main/%E6%96%87%E7%AB%A0/%E5%9F%BA%E4%BA%8ERust%E7%9A%84Android%20Native%E5%86%85%E5%AD%98%E5%88%86%E6%9E%90%E6%96%B9%E6%A1%88.md) 282 | - [Rust 与 C++:深入的语言比较](https://github.com/0voice/Understanding_in_Rust/blob/main/%E6%96%87%E7%AB%A0/Rust%20%E4%B8%8E%20C%2B%2B%EF%BC%9A%E6%B7%B1%E5%85%A5%E7%9A%84%E8%AF%AD%E8%A8%80%E6%AF%94%E8%BE%83.md) 283 | 284 | # 📰 官方文档 285 | 286 | - [标准库API文档](https://doc.rust-lang.org/std/) 287 | - [Rust Reference](https://doc.rust-lang.org/reference/index.html): Rust reference 文档,有中文翻译版本 [Rust语言规范](https://rustlang-cn.org/office/rust/reference/) 正在翻译过程中 288 | - [Rust编译错误索引](https://doc.rust-lang.org/error-index.html):发生编译错误时,可以通过索引找到具体错误解释 289 | - [rustdoc文档](https://doc.rust-lang.org/rustdoc/): `restdoc`工具的使用文档 290 | - [Rustonomicon](https://doc.rust-lang.org/reference/): rust的参考文档。但是目前并不完整,可能有遗漏和错误 291 | - [Unstable Book](https://doc.rust-lang.org/unstable-book/): 用于尚不稳定特性的文档 292 | - [Rustonomicon](https://doc.rust-lang.org/nomicon/): unsafe rust的黑暗艺术,有中文翻译版本 [Rust高级编程](https://rustlang-cn.org/office/rust/advrust/) 293 | - [The Cargo Book](https://doc.rust-lang.org/cargo/index.html): cargo使用介绍,有中文翻译版本 [Cargo教程](https://rustlang-cn.org/office/rust/cargo/) 正在进行中 294 | - [Rust Edition Guide](https://doc.rust-lang.org/nightly/edition-guide/introduction.html): Rust 版本指南,传递 Rust 不同版本之间大的变更信息 295 | - [Command line apps in Rust](https://rust-lang-nursery.github.io/cli-wg/#command-line-apps-in-rust): 在Rust中编写命令行程序 296 | 297 | # ✈ 杂货铺 298 | 299 | - Rust 最大中文社区论坛:https://rustcc.cn/ 300 | - 小众中文社区的翻译资料/论坛:https://learnku.com/rust 301 | - Rust在线编辑器: https://play.rust-lang.org/ 302 | - 2021 年去哪学 Rust:https://loige.co/where-to-go-to-learn-rust-in-2021/ 303 | - Rust Cheat Sheet(Rust语法备忘单):https://cheats.rs/ 304 | - Rust 中文书架与资讯:https://budshome.com/ | https://blog.budshome.com/ 305 | - 简要而基础的 Rust 知识(适合在 Rust Book 阶段当作补充材料):https://learning-rust.github.io/ 306 | - 微软发布的 Rust 新手教程:https://docs.microsoft.com/en-us/learn/paths/rust-first-steps/ 307 | - Rust-leetcodes刷题:https://stevenbai.top/rust-leetcode/ 308 | - Rust by Example 通过例子学 Rust:https://doc.rust-lang.org/rust-by-example/index.html 309 | - 电子书下载 :https://jp1lib.org/s/Rust 310 | - Rust线下全球会议: 311 | - RustConf: https://rustconf.com/ 312 | - Rust Belt Rust: https://rust-belt-rust.com/ 313 | - RustFest: https://blog.rustfest.eu/ 314 | - Rust Latam: https://rustcon.asia/ 315 | - RustCon Asia: https://rustcon.asia/ 316 | 317 | # 💽 视频 318 | 319 | Rust 验证研讨会 2021 | 320 | :------:| 321 | [Peeking at compiler-internal data (for fun and profit)](https://www.aliyundrive.com/s/4N4EE3URbBT)| 322 | [Ferrite- A Rust EDSL for Message-passing Protocol Verification](https://www.aliyundrive.com/s/hGpvaNzWAHS)| 323 | [Verifying that Rust programs don't crash](https://www.aliyundrive.com/s/TiMG3B7XXyZ)| 324 | [crux-mir- Symbolic testing for Rust](https://www.aliyundrive.com/s/j5LG8Lwdmx8)| 325 | [RustBelt- A Quick Dive Into the Abyss](https://www.aliyundrive.com/s/iv3ohCTjzcs)| 326 | [Rustv- Semi-automatic Verification of Unsafe Rust Programs](https://www.aliyundrive.com/s/bfQjMdJTvow)| 327 | [Polonius](https://www.aliyundrive.com/s/bNdQLDpKbzN)| 328 | [Towards Automatic Verification of Unsafe Rust with Constrained Horn Solvers](https://www.aliyundrive.com/s/iW2SdR1pFGU)| 329 | [Rust interest in safety- and mission-critical environments](https://www.aliyundrive.com/s/EXnsFymhCib)| 330 | [Prusti – Deductive Verification for Rust](https://www.aliyundrive.com/s/eph1UzJugSt)| 331 | [Creusot- A prototype tool for verification of Rust software](https://www.aliyundrive.com/s/6aeaQNeGZbX)| 332 | [hacspec_ succinct, executable, verifiable specifications for high-assurance cryptography](https://www.aliyundrive.com/s/DgfNNFRn45G)| 333 | [Leveraging Compiler Intermediate Representation for Multi- and Cross-Language Verification](https://www.aliyundrive.com/s/oWuWB37ByBH)| 334 | 335 |
336 | 337 | Rust Linz 2021 | 338 | :------:| 339 | [Rust Linz, July 2021 - Stefan Baumgartner - Serverless Rust](https://www.aliyundrive.com/s/7nBT4iWyT5p)| 340 | [Rust Linz, July 2021 - Rainer Stropek - Traits, not your grandparents' interfaces](https://www.aliyundrive.com/s/1fSbir945Sh)| 341 | [Rust Linz, August 2021 - Rainer Stropek - Rust iterators](https://www.aliyundrive.com/s/G3Yu2U7DaXN)| 342 | [Rust Linz, May 2021 - Harald Reingruber - Rust for Medical Visualization](https://www.aliyundrive.com/s/5u27AdX5bhq)| 343 | [Rust Linz, May 2021 - Lisa Passing - Creative Rust](https://www.aliyundrive.com/s/WouXfuZ9VSU)| 344 | [Rust Linz, June 2021 - Tim McNamara - How to learn Rust](https://www.aliyundrive.com/s/XhSexAWPNKr)| 345 | [Rust Linz, June 2021 - JT - A new path for your shell](https://www.aliyundrive.com/s/cymDeWwbsr6)| 346 | [Rust Linz x Global Azure, April 2021 - Ryan Levick & Thomas Taylor - Rust, Kubernetes, and the Cloud](https://www.aliyundrive.com/s/Gdd63ojU9Xc)| 347 | [Rust Linz, April 2021 - Jan-Erik Rediger - Leveraging Rust to build cross-platform libraries](https://www.aliyundrive.com/s/rfPAYT9NWi9)| 348 | [Rust Linz, April 2021 - Herbert Wolverson - Learning Rust with Game Development - YouTube](https://www.aliyundrive.com/s/AoLEhwsgv9P)| 349 | 350 | 351 | 352 | # 🏗 开源框架 353 | 354 | ## 值得新手关注的Rust项目 355 | 356 | - [mini redis](https://github.com/tokio-rs/mini-redis) - 不完整的Redis客户端和服务器实现使用Tokio -仅为学习目的 357 | - [async-graphql](https://github.com/sunli829/async-graphql) - 一个在Rust中实现的GraphQL服务器库 358 | 359 | ## 应用程序 360 | 361 | - [alacritty](https://github.com/alacritty/alacritty) — 跨平台、GPU 增强的终端模拟器 362 | - [AnderEnder/s3find-rs](https://github.com/AnderEnder/s3find-rs) — 用于遍历 Amazon S3 层次结构的命令行实用程序,类似于 Amazon S3 的 find 363 | - [andschwa/rust-genetic-algorithm](https://github.com/andschwa/rust-genetic-algorithm) — 一种用于学术基准问题的遗传算法 364 | - [asm-cli-rust](https://github.com/cch123/asm-cli-rust) — 一个用 Rust 编写的交互式程序集外壳. 365 | - [ballista](https://github.com/ballista-compute/ballista) — 使用 Rust、Apache Arrow 和 Kubernetes 的分布式计算平台的 PoC! 366 | - [cloudflare/boringtun](https://github.com/cloudflare/boringtun) — 用户空间 WireGuard VPN 实现 367 | - [darrint/device-blocker](https://github.com/darrint/device-blocker) — 通过阻止家庭 Wifi 路由器上的互联网访问来限制儿童各种移动设备的屏幕时间. 368 | - [denoland/deno](https://github.com/denoland/deno) — 使用 V8、Rust 和 Tokio 构建的安全 JavaScript/TypeScript 运行时 369 | - [dlecan/generic-dns-update](https://github.com/dlecan/generic-dns-update) — 使用您的 IP 地址更新 DNS 区域文件的工具 370 | - [Factotum](https://github.com/snowplow/factotum) — [A system to programmatically run data pipelines](https://snowplowanalytics.com/blog/2016/04/09/introducing-factotum-data-pipeline-runner/) 371 | - [fcsonline/drill](https://github.com/fcsonline/drill) — 受 Ansible 语法启发的 HTTP 负载测试应用程序 372 | - [Fractalide](https://github.com/fractalide/fractalide) — 简单的 Rust 微服务 373 | - [habitat](https://community.chef.io/tools/chef-habitat) — 一个工具 [Chef](https://www.chef.io/) 构建、部署和管理应用程序. 374 | - [Herd](https://github.com/imjacobclark/Herd) — 一个实验性的 HTTP 负载测试应用程序 375 | - [intecture/api](https://github.com/intecture/api) — API 驱动的服务器管理和配置工具 376 | - [ivanceras/diwata](https://github.com/ivanceras/diwata) — postgresql 的数据库管理工具 377 | - [jedisct1/flowgger](https://github.com/awslabs/flowgger) — 快速、简单和轻量级的数据收集器 378 | - [kbknapp/docli](https://github.com/kbknapp/docli-rs) — 用于管理 DigitalOcean 基础设施的命令行实用程序 379 | - [kytan](https://github.com/changlan/kytan) — 高性能点对点 VPN 380 | - [limonite](https://crates.io/crates/limonite) — 静态博客 / 网站生成器 381 | - [linkerd/linkerd2-proxy](https://github.com/linkerd/linkerd2-proxy) — Kubernetes 的超轻服务网格. 382 | - [MaidSafe](https://maidsafe.net/) — 一个去中心化的平台. 383 | - [mdBook](https://crates.io/crates/mdbook) — 从 Markdown 文件创建书籍的命令行实用程序 384 | - [nicohman/eidolon](https://github.com/nicohman/eidolon) — 适用于 linux 和 macosx 的无 Steam 和 drm 游戏注册表和启动器 385 | - [notty](https://github.com/withoutboats/notty) — 一种新型终端 386 | - [Pijul](https://pijul.org/) — 基于补丁的分布式版本控制系统 387 | - [rsign](https://crates.io/crates/rsign) — 一个简单的命令行工具,用于生成 / 签署 / 验证旨在与 Minisign 兼容的数字签名 388 | - [Rudr](https://github.com/oam-dev/rudr) — Kubernetes 实现 [Open Application Model](https://oam.dev/) 规格 389 | - [rx](https://github.com/cloudhead/rx) — 受 Vi 启发的现代像素艺术编辑器 390 | - [Sandstorm Collections App](https://github.com/sandstorm-io/collections-app) 391 | - [Servo](https://github.com/servo/servo) — 原型 Web 浏览器引擎 392 | - [tiny](https://github.com/osa1/tiny) — 终端 IRC 客户端 393 | - [trust-dns](https://crates.io/crates/trust-dns) — DNS 服务器 394 | - [updns](https://github.com/wyhaya/updns) — DNS 代理工具 395 | - [Weld](https://github.com/serayuzgur/weld) — 全假 REST API 生成器 396 | - [wezterm](https://github.com/wez/wezterm) — 一个gpu加速的跨平台终端模拟器和多路复用器 397 | 398 | ### 音频和音乐技术 399 | 400 | - [enginesound](https://github.com/DasEtwas/enginesound) — 用于按程序生成半逼真引擎声音的 GUI 和命令行应用程序. 具有深度配置、可变采样率和频率分析窗口. 401 | - [indiscipline/zrtstr](https://github.com/indiscipline/zrtstr) — 用于检查立体声 wav 文件是否为仿立体声(即具有相同通道)并将此类文件转换为单声道的命令行实用程序. 402 | - [Lyriek](https://github.com/bartwillems/lyriek) — 一个多线程 GTK 3 应用程序,用于获取当前播放歌曲的歌词. 403 | - [Phate6660/musinfo](https://github.com/Phate6660/musinfo) — 从 mpd 查询音乐信息并将其显示在通知中的程序. 404 | - [Phate6660/rsmpc](https://github.com/Phate6660/rsmpc) — mpc 的实现,但不是直接实现,因为会有一些差异. 405 | - [Phate6660/rsmpc](https://github.com/Phate6660/rsmpc-gui) — 用于 mpd 的 gtk 前端. 406 | - [Polaris](https://github.com/agersant/polaris) — 音乐流媒体应用程序. 407 | - [Spotify TUI](https://github.com/Rigellute/spotify-tui) — 一个用 Rust 编写的用于终端的 Spotify 客户端. 408 | - [Spotifyd](https://github.com/Spotifyd/spotifyd) — 作为 UNIX 守护程序运行的开源 Spotify 客户端. 409 | 410 | ### 加密数字货币 411 | 412 | - [Bitcoin Satoshi's Vision](https://github.com/brentongunning/rust-sv) — 用于处理比特币 SV 的 Rust 库. 413 | - [cardano-cli](https://github.com/input-output-hk/cardano-cli) — 卡尔达诺命令行界面 (CLI) 414 | - [ChainX](https://github.com/chainx-org/ChainX) — Polkadot 上完全去中心化的链间加密资产管理. 415 | - [CITA](https://github.com/citahub/cita) — 面向企业用户的高性能区块链内核. 416 | - [coinbase-pro-rs](https://github.com/inv2004/coinbase-pro-rs) — Rust 中的 Coinbase pro 客户端,支持同步 / 异步 / websocket 417 | - [ethaddrgen](https://github.com/Limeth/ethaddrgen) — 用 Rust 制作的自定义以太坊虚地址生成器 418 | - [Grin](https://github.com/mimblewimble/grin/) — MimbleWimble 协议的演变 419 | - [hdwallet](https://github.com/jjyr/hdwallet) — BIP-32 HD 钱包相关的密钥推导实用程序. 420 | - [Holochain](https://github.com/holochain/holochain) — 区块链的可扩展 P2P 替代方案,适用于您一直想要构建的所有分布式应用程序. 旧仓库的链接是 [this](https://github.com/holochain/holochain-rust) 不再维护.[ibc-rs](https://github.com/informalsystems/ibc-rs) - Rust 的实现 [Interblockchain Communication](https://xn--ibc-3h3e109w.org/) 协议 421 | - [infincia/bip39-rs](https://github.com/infincia/bip39-rs) — BIP39 的 Rust 实现. 422 | - [Joystream](https://github.com/Joystream/joystream) — 一个用户管理的视频平台 423 | - [Diem](https://github.com/diem/diem) — Diem 的使命是建立一个简单的全球货币和金融基础设施,为数十亿人赋能. 424 | - [Lighthouse](https://github.com/sigp/lighthouse) — Rust Ethereum 2.0 客户端 425 | - [near/nearcore](https://github.com/near/nearcore) — 用于低端移动设备的去中心化智能合约平台. 426 | - [Nervos CKB](https://github.com/nervosnetwork/ckb) — Nervos CKB 是一个公共的免许可区块链,是 Nervos 网络的公共知识层. 427 | - [Nimiq](https://github.com/nimiq/core-rs) — Nimiq 节点的 Rust 实现 428 | - [Parity-Bitcoin](https://github.com/paritytech/parity-bitcoin) — Parity 比特币客户端 429 | - [Parity-Bridge](https://github.com/paritytech/parity-bridge) — 任何两个基于以太坊的网络之间的桥梁 430 | - [Parity-Ethereum](https://github.com/openethereum/openethereum) — 快速、轻便、强大的以太坊客户端 431 | - [Parity-Zcash](https://github.com/paritytech/parity-zcash) — Zcash 协议的 Rust 实现 432 | - [Phala-Network/phala-blockchain](https://github.com/Phala-Network/phala-blockchain) — 基于 Intel SGX 和 Substrate 的机密智能合约区块链 433 | - [Polkadot](https://github.com/paritytech/polkadot) — 具有集中安全性的异构多链技术 434 | - [rbtc](https://github.com/lucawen/rbtc) — 将 BTC 转换为任何货币,反之亦然. 435 | - [rust-cardano](https://github.com/input-output-hk/rust-cardano) — Cardano 原语、助手和相关应用程序的 Rust 实现 436 | - [Substrate](https://github.com/paritytech/substrate) — 用 Rust 编写的通用模块化区块链模板 437 | - [tendermint-rs](https://github.com/informalsystems/tendermint-rs) - Tendermint 区块链数据结构和客户端的 Rust 实现 438 | - [wagyu](https://github.com/AleoHQ/wagyu) [[wagyu](https://crates.io/crates/wagyu)] — 用于生成加密货币钱包的 Rust 库 439 | - [zcash](https://github.com/zcash/zcash) — Zcash 是 “Zerocash” 协议的实现. 440 | - [YeeCo yeeroot](https://github.com/yeeco/yeeroot) — YeeCo yeeroot 是一个无需许可、安全、高性能和可扩展的公共区块链平台,由基于 Rust 编写的 PoW 共识的全分片技术提供支持 441 | 442 | ### 数据库 443 | 444 | - [indradb](https://crates.io/crates/indradb) — 基于 Rust 的图形数据库 445 | - [Materialize](https://github.com/MaterializeInc/materialize) - 由 Timely Dataflow 提供支持的流式 SQL 数据库:heavy_dollar_sign 446 | - [noria](https://crates.io/crates/noria) — 用于 Web 应用程序后端的动态变化、部分状态的数据流 447 | - [Lucid](https://github.com/lucid-kv/lucid) — High performance and distributed KV store accessible through a HTTP API. 448 | - [ParityDB](https://github.com/paritytech/parity-db) — 快速可靠的数据库,针对读操作进行了优化 449 | - [PumpkinDB](https://github.com/PumpkinDB/PumpkinDB) — 事件溯源数据库引擎 450 | - [seppo0010/rsedis](https://github.com/seppo0010/rsedis) — Rust 中的 Redis 重新实现 451 | - [Skytable](https://github.com/skytable/skytable) — 多模型 NoSQL 数据库 452 | - [tikv](https://github.com/tikv/tikv) — Rust 中的分布式 KV 数据库 453 | - [sled](https://crates.io/crates/sled) —(测试版)现代嵌入式数据库 454 | - [TerminusDB](https://github.com/terminusdb/terminusdb-store) - 开源图形数据库和文档存储 455 | 456 | ### 模拟器 457 | 458 | - [kondrak/rust64](https://github.com/kondrak/rust64) 459 | - [Ruffle](https://github.com/ruffle-rs/ruffle) — Ruffle 是用 Rust 编程语言编写的 Adobe Flash Player 模拟器. Ruffle 使用 WebAssembly 面向桌面和 Web. 460 | - [Gekkio/mooneye-gb](https://github.com/Gekkio/mooneye-gb) 461 | - [mvdnes/rboy](https://github.com/mvdnes/rboy) 462 | - [NivenT/RGB](https://github.com/nivent/RGB) 463 | - [mohanson/gameboy](https://github.com/mohanson/gameboy) — 全功能跨平台 GameBoy 模拟器. 永远的男孩! 464 | - [michelhe/rustboyadvance-ng](https://github.com/michelhe/rustboyadvance-ng) - RustboyAdvance-ng 是一款 Gameboy Advance 模拟器,具有桌面、安卓和 [WebAssembly](https://michelhe.github.io/rustboyadvance-ng/) 支持. 465 | - [iamsix/oxidenes](https://github.com/iamsix/oxidenes) 466 | - [koute/pinky](https://github.com/koute/pinky) 467 | - [pcwalton/sprocketnes](https://github.com/pcwalton/sprocketnes) 468 | - [Amjad50/plastic](https://github.com/Amjad50/plastic) — plastis 是一个用 Rust 构建的全功能 NES 模拟器. 469 | - [rustation-ng](https://gitlab.com/flio/rustation-ng/) — 使用 Rust 的 Playstation 模拟器 470 | - [pacmancoder/rustzx](https://github.com/pacmancoder/rustzx) 471 | - [rodrigorc/raze](https://github.com/rodrigorc/raze) — 对于 WebAssembly, [live version here](https://rodrigorc.github.io/raze/) * 虚拟男孩 472 | - [emu-rs/rustual-boy](https://github.com/emu-rs/rustual-boy) 473 | - [mohanson/i8080](https://github.com/mohanson/i8080) — Rust 的 Intel 8080 cpu 模拟器 474 | 475 | ### 游戏 476 | 477 | - [lifthrasiir/angolmois-rust](https://github.com/lifthrasiir/angolmois-rust) — 一款支持 BMS 格式的极简音乐视频游戏 478 | - [citybound](https://github.com/citybound/citybound) - 你应得的城市模拟 479 | - [schulke-214/connect-four](https://github.com/schulke-214/connect-four) — 一个简单的连接四个实现. 480 | - [doukutsu-rs](https://github.com/doukutsu-rs/doukutsu-rs) — 对 Cave Story 引擎的 Rust 重新实现,并进行了一些增强. 481 | - [rsaarelm/magog](https://github.com/rsaarelm/magog) — Rust 中的 roguelike 游戏 482 | - [schulke-214/rsnake](https://github.com/schulke-214/rsnake) — 用 Rust 编写的 Snake. 483 | - [soydos](https://github.com/soydos/pusoy_dos2) — Pusoy Dos 的 wasm 实现 484 | - [cristicbz/rust-doom](https://github.com/cristicbz/rust-doom) — Doom 的渲染器,可能会发展成为一款可玩的游戏 485 | - [Thinkofname/rust-quake](https://github.com/Thinkofname/rust-quake) — Rust 中的地震地图渲染器 486 | - [rhex](https://github.com/dpc/rhex) — 六边形 ascii roguelike 487 | - [garkimasera/rusted-ruins](https://github.com/garkimasera/rusted-ruins) - 具有像素艺术的可扩展开放世界流氓游戏 488 | - [Veloren](https://gitlab.com/veloren/veloren) — 一个开放世界、开源的多人体素 RPG 游戏,目前处于 alpha 开发阶段 489 | - [swatteau/sokoban-rs](https://github.com/swatteau/sokoban-rs) — 推箱子实现 490 | - [aleshaleksey/TGWM](https://github.com/aleshaleksey/TGWM) — 具有回合制机制的 RPG(正在进行中) 491 | - [ozkriff/zemeroth](https://github.com/ozkriff/zemeroth) — 一款小型 2D 回合制六角策略游戏 492 | - [Zone of Control](https://github.com/ozkriff/zoc) — 回合制六角策略游戏 493 | - [phantomion/snake_game](https://github.com/phantomion/snake_game) - 用 Rust 编写的简单终端蛇游戏. 494 | 495 | ### 图形处理 496 | 497 | - [Limeth/euclider](https://github.com/Limeth/euclider) — 实时 4D CPU 光线追踪器 498 | - [RazrFalcon/resvg](https://github.com/RazrFalcon/resvg) — 一个 SVG 渲染库. 499 | - [ivanceras/svgbob](https://github.com/ivanceras/svgbob) — 将 ASCII 图转换为 SVG 图形 500 | - [RazrFalcon/svgcleaner](https://github.com/RazrFalcon/svgcleaner) — 整理 SVG 图形 501 | - [Twinklebear/tray_rust](https://github.com/Twinklebear/tray_rust) — 光线追踪器 502 | - [turnage/valora](https://crates.io/crates/valora) — 生成美术图书馆 503 | - [mikigraf/Image-Processing-CLI-in-Rust](https://github.com/mikigraf/Image-Processing-CLI-in-Rust) — 用于处理图像、生成直方图的 CLI. 504 | 505 | ### 工业自动化 506 | 507 | - [locka99/opcua](https://github.com/locka99/opcua) — [OPC UA](https://opcfoundation.org/about/opc-technologies/opc-ua/) 图书馆. 508 | - [slowtec/tokio-modbus](https://github.com/slowtec/tokio-modbus) - 一种 [tokio](https://tokio.rs/)-based [modbus](https://modbus.org/) 图书馆. 509 | - [BiancoRoyal/modbus-iiot-rust](https://github.com/BiancoRoyal/modbus-iiot-rust) — 纯锈 [modbus](https://modbus.org/) 没有或更少依赖的库. 510 | 511 | ### 可观察性工具 512 | 513 | - [timberio/vector](https://github.com/timberio/vector) — 高性能、日志、指标和事件路由器. 514 | - [Mnwa/gtsa](https://github.com/Mnwa/gtsa) — 将 gelf 消息(Graylog 的消息)代理到 Sentry 的简单解决方案 515 | - [OpenTelemetry](https://crates.io/crates/opentelemetry) — OpenTelemetry 提供一组 API、库、代理和收集器服务,以从您的应用程序中捕获分布式跟踪和指标. 您可以使用 Prometheus、Jaeger 和其他可观察性工具分析它们. 516 | 517 | ### 操作系统 518 | 519 | - [nebulet/nebulet](https://github.com/nebulet/nebulet) — 实现在 Ring 0 中运行的 WebAssembly“用户模式” 的微内核. 520 | - [redox-os/redox](https://gitlab.redox-os.org/redox-os/redox) 521 | - [thepowersgang/rust_os](https://github.com/thepowersgang/rust_os) 522 | - [tock/tock](https://github.com/tock/tock) — 适用于基于 Cortex-M 的微控制器的安全嵌入式操作系统 523 | 524 | ### 生产能力 525 | 526 | - [espanso](https://github.com/federico-terzi/espanso) — 一个用 Rust 编写的跨平台文本扩展器 [eureka](https://crates.io/crates/eureka) — 无需离开终端即可输入和存储您的想法的 CLI 工具 527 | - [pier-cli/pier](https://github.com/pier-cli/pier) — 用于管理(添加、搜索元数据等)所有单行程序、脚本、工具和 CLI 的中央存储库 528 | - [subilo](https://github.com/Bansco/subilo) - 持续部署代理 529 | 530 | ### 安全工具 531 | 532 | - [kpcyrd/authoscope](https://github.com/kpcyrd/authoscope) — 一个可编写脚本的网络认证破解器 533 | - [lethe](https://github.com/kostassoid/lethe) — 安全的跨平台驱动器擦除实用程序 534 | - [arvancloud/libinjection-rs](https://github.com/arvancloud/libinjection-rs) — Rust 绑定 [libinjection](https://github.com/client9/libinjection) 535 | - [ripasso](https://github.com/cortex/ripasso/) — 密码管理器,与 pass 兼容的文件系统 536 | - [kpcyrd/rshijack](https://github.com/kpcyrd/rshijack) — 一个 TCP 连接劫持者,对 shijack 进行 Rust 重写 537 | - [rustscan/rustscan](https://github.com/RustScan/RustScan) — 使用此端口扫描工具使 Nmap 更快 538 | - [kpcyrd/sniffglue](https://github.com/kpcyrd/sniffglue) — 一个安全的多线程数据包嗅探器 539 | - [kpcyrd/sn0int](https://github.com/kpcyrd/sn0int) — 半自动 OSINT 框架和包管理器 540 | 541 | ### 系统工具 542 | 543 | - [ajeetdsouza/zoxide](https://github.com/ajeetdsouza/zoxide/) — 一种快速替代 `cd` 的方法,可以学习你的习惯 544 | - [bandwhich](https://github.com/imsnif/bandwhich) — 终端带宽利用工具 545 | - [brocode/fblog](https://github.com/brocode/fblog) — 小型命令行 JSON 日志查看器 546 | - [buster/rrun](https://github.com/buster/rrun) — Linux 的命令启动器,类似于 gmrun 547 | - [cristianoliveira/funzzy](https://github.com/cristianoliveira/funzzy) — 受启发的可配置文件系统观察器 [entr](http://eradman.com/entrproject/) 548 | - [dalance/procs](https://github.com/dalance/procs) — Rust 编写的 “ps” 的现代替代品 549 | - [diskonaut](https://github.com/imsnif/diskonaut) — 终端可视化磁盘空间导航器 550 | - [dust](https://github.com/bootandy/dust) — 更直观的 du 版本 551 | - [ddh](https://github.com/darakian/ddh) — 快速重复文件查找器 552 | - [fselect](https://crates.io/crates/fselect) — 使用类似 SQL 的查询查找文件 553 | - [gitui](https://github.com/extrawurst/gitui) - 用 Rust 编写的 git 快速终端客户端. 554 | - [k0pernicus/zou](https://github.com/k0pernicus/zou) — 下载加速器 555 | - [Kondo](https://github.com/tbillington/kondo) - 用于删除软件项目工件和回收磁盘空间的 CLI 和 GUI 工具 556 | - [lotabout/rargs](https://github.com/lotabout/rargs) [[rargs](https://crates.io/crates/rargs)] — 支持模式匹配的 xargs + awk 557 | - [lotabout/skim](https://github.com/lotabout/skim) — 纯锈的模糊取景器 558 | - [mitnk/cicada](https://github.com/mitnk/cicada) — 一个类似 bash 的 Unix shell 559 | - [mmstick/concurr](https://github.com/mmstick/concurr) — 带有客户端 - 服务器架构的 GNU Parallel 的替代方案 560 | - [mmstick/fontfinder](https://github.com/mmstick/fontfinder) — 用于预览和安装 Google 字体的 GTK3 应用程序 561 | - [mmstick/parallel](https://github.com/mmstick/parallel) — 重新实现 GNU Parallel 562 | - [mmstick/tv-renamer](https://github.com/mmstick/tv-renamer) — 带有可选 GTK3 前端的电视剧重命名应用程序. 563 | - [nushell/nushell](https://github.com/nushell/nushell) — 一个新型Shell. 564 | - [organize-rt](https://gitlab.com/FixFromDarkness/organize-rt) — 根据正则表达式规则组织文件(默认为文件扩展名). 565 | - [orhun/kmon](https://github.com/orhun/kmon) — Linux 内核管理器和活动监视器 566 | - [Peltoche/lsd](https://github.com/Peltoche/lsd) — 一个 ls 有很多漂亮的颜色和很棒的图标 567 | - [ogham/exa](https://github.com/ogham/exa) — 'ls' 的替代品 568 | - [pop-os/debrep](https://github.com/pop-os/debrepbuild) — 用于构建和管理 APT 存储库的 APT 存储库工具 569 | - [pop-os/popsicle](https://github.com/pop-os/popsicle) — GTK3 和 CLI 实用程序,用于并行刷新多个 USB 设备 570 | - [pueue](https://github.com/nukesor/pueue) — 管理您长时间运行的 shell 命令. 571 | - [Luminarys/synapse](https://github.com/Luminarys/synapse) — 灵活且快速的 BitTorrent 守护进程. 572 | - [pop-os/system76-power](https://github.com/pop-os/system76-power/) — 带有 CLI 工具的 Linux 电源管理守护进程(DBus 接口). 573 | - [mxseev/logram](https://github.com/mxseev/logram) — 将日志文件的更新推送到 Telegram 574 | - [redox-os/ion](https://github.com/redox-os/ion) — 下一代系统外壳 575 | - [jamesbirtles/hotkey-rs](https://github.com/jamesbirtles/hotkey-rs) — 在 Rust 中收听全局热键的库 576 | - [nivekuil/rip](https://github.com/nivekuil/rip) - 一种安全且符合人体工程学的替代`rm` 577 | - [sharkdp/bat](https://github.com/sharkdp/bat) — 有翅膀的 cat(1) 克隆体. 578 | - [sharkdp/fd](https://github.com/sharkdp/fd) — 一种简单、快速且用户友好的查找替代方案. 579 | - [sitkevij/hex](https://github.com/sitkevij/hex) — 彩色的 hexdump 终端实用程序. 580 | - [slai11/goto](https://github.com/slai11/goto) — 跳转到索引目录的简单且用户友好的方式. 581 | - [m4b/bingrep](https://github.com/m4b/bingrep) — 通过来自各种操作系统和体系结构的二进制文件进行 Greps,并为它们着色. 582 | - [uutils/coreutils](https://github.com/uutils/coreutils) — GNU coreutils 的跨平台 Rust 重写 583 | - [watchexec](https://github.com/watchexec/watchexec) — 执行命令以响应文件修改 584 | - [XAMPPRocky/tokei](https://github.com/XAMPPRocky/tokei) — 计算代码行数 585 | - [yake](https://crates.io/crates/yake) — Yake 是一个基于 yaml 文件的任务运行器 586 | - [ytop](https://github.com/cjbassi/ytop) - 一个用 Rust 编写的 TUI 系统监视器 587 | - [cocom](https://github.com/LamdaLamdaLamda/cocom) - 纯粹用 Rust 编写的 NTP 客户端. 588 | 589 | ### 文字编辑器 590 | 591 | - [amp](https://amp.rs/) — 受 Vi/Vim 的启发. 592 | - [gchp/iota](https://github.com/gchp/iota) — 一个简单的文本编辑器 593 | - [ilai-deutel/kibi](https://github.com/ilai-deutel/kibi) — 具有语法高亮、增量搜索等功能的小型 (≤1024 LOC) 文本编辑器. 594 | - [vamolessa/pepper](https://github.com/vamolessa/pepper) [[pepper](https://crates.io/crates/pepper)] — 一个自以为是的模式编辑器,可简化从终端进行的代码编辑 595 | - [mathall/rim](https://github.com/mathall/rim) — 用 Rust 编写的类似 Vim 的文本编辑器 596 | - [ox](https://github.com/curlpipe/ox) — 在终端中运行的独立 Rust 文本编辑器! 597 | - [Remacs](https://github.com/remacs/remacs) — 社区驱动的 Emacs 到 Rust 的移植. 598 | - [xi-editor](https://github.com/xi-editor/xi-editor) — 一个现代编辑器,后端是用 Rust 编写的. 599 | - [xray](https://github.com/atom-archive/xray) — 实验性的下一代基于电子的文本编辑器. 600 | 601 | ### 文本处理 602 | 603 | - [cpc](https://github.com/probablykasper/cpc) - 解析和计算数学字符串,支持单位和单位转换,从 “1+2” 到“1% 的回合(1 光年 / 14!s 到公里 / 小时)”. 604 | - [grex](https://github.com/pemistahl/grex) — 用于从用户提供的测试用例生成正则表达式的命令行工具和库 605 | - [dmerejkowsky/ruplacer](https://github.com/dmerejkowsky/ruplacer) — 在源文件中查找和替换文本 606 | - [ripgrep](https://crates.io/crates/ripgrep) — 结合了 Silver Searcher 的可用性和 grep 的原始速度 607 | - [phiresky/ripgrep-all](https://github.com/phiresky/ripgrep-all) — ripgrep,还可以搜索 PDF、电子书、Office 文档、zip、tar.gz 等. 608 | - [replicadse/complate](https://github.com/replicadse/complate) — 一种终端内文本模板工具,用于标准化消息(如 GIT 提交). 609 | - [sd](https://crates.io/crates/sd) — 直观的查找和替换 CLI 610 | - [lavifb/todo_r](https://github.com/lavifb/todo_r) — 用一个命令查找所有 TODO 笔记! 611 | - [whitfin/runiq](https://github.com/whitfin/runiq) — 从未排序的输入中过滤重复行的有效方法. 612 | - [whitfin/bytelines](https://github.com/whitfin/bytelines) — 将输入行读取为字节片以提高效率. 613 | - [vishaltelangre/ff](https://github.com/vishaltelangre/ff) — 按名称查找文件 (ff)! 614 | - [xsv](https://crates.io/crates/xsv) — 一个快速的 CSV 命令行工具(切片、索引、选择、搜索、采样等) 615 | - [Lisprez/so_stupid_search](https://github.com/Lisprez/so_stupid_search) — 一个简单快速的人类字符串搜索工具 616 | 617 | ### 图像处理 618 | 619 | - [Imager](https://github.com/imager-io/imager) — 自动图像优化. 620 | 621 | ### 实用工具 622 | 623 | - [aleshaleksey/AZDice](https://github.com/aleshaleksey/AZDice) — 桌面家庭酿酒商的骰子成功分发生成器. 624 | - [yaa110/cb](https://github.com/yaa110/cb) — 管理剪贴板的命令行界面 625 | - [brycx/checkpwn](https://github.com/brycx/checkpwn) — 一个 Have I Being Pwned (HIBP) 命令行实用工具,可让您轻松检查被盗用的帐户和密码. 626 | - [vamolessa/copycat](https://github.com/vamolessa/copycat) [[copycat](https://crates.io/crates/copycat)] — 一个简单的剪贴板 cli 界面,适用于具有文本和 bmp 支持的窗口 627 | - [evansmurithi/cloak](https://github.com/evansmurithi/cloak) — 命令行 OTP(一次性密码)身份验证器应用程序. 628 | - [replydev/cotp](https://github.com/replydev/cotp) - 与外部备份兼容的值得信赖的加密一次性密码验证器应用程序. 629 | - [rustdesk/rustdesk](https://github.com/rustdesk/rustdesk) - 远程桌面应用程序. 630 | - [arthrp/consoletimer](https://github.com/arthrp/consoleTimer) — 终端的简单计时器. 631 | - [tversteeg/emplace](https://github.com/tversteeg/emplace) — 在多台机器上同步已安装的包 632 | - [unrelentingtech/freepass](https://github.com/unrelentingtech/freepass) — 高级用户的免费密码管理器. 633 | - [yoannfleurydev/gitweb](https://github.com/yoannfleurydev/gitweb) — 在浏览器中打开当前远程存储库. 634 | - [mme](https://github.com/GoberInfinity/mme) — 命令行工具来记住您有时忘记的命令. 635 | - [raftario/licensor](https://github.com/raftario/licensor) — 将许可证写入标准输出 636 | - [arthrp/quick-skeleton](https://github.com/arthrp/quick-skeleton) — 项目脚手架工具,类似于 Yeoman 和 Slush. 637 | - [repoch](https://github.com/lucawen/repoch) — 将纪元转换为日期时间,将日期时间转换为纪元 638 | - [whitfin/s3-concat](https://github.com/whitfin/s3-concat) — 使用灵活模式远程连接 Amazon S3 文件的命令行工具. 639 | - [whitfin/s3-meta](https://github.com/whitfin/s3-meta) — 用于收集有关 Amazon S3 存储桶的元数据的命令行工具. 640 | - [whitfin/s3-utils](https://github.com/whitfin/s3-utils) — 一个包含基于 Amazon S3 的实用程序的小工具,可提供额外的便利 API. 641 | - [gorros/s3-edit-rs](https://github.com/gorros/s3-edit-rs) — 直接在 Amazon S3 上编辑文件的命令行工具. 642 | - [fcsonline/tmux-thumbs](https://github.com/fcsonline/tmux-thumbs) — 用 Rust 编写的 tmux-finger 的闪电般快速版本,像 vimium/vimperator 一样复制 / 粘贴 tmux. 643 | - [amar-laksh/workstation](https://github.com/amar-laksh/workstation) — 一个命令行工具,可帮助您管理工作站,让您远离屏幕、在您不在时锁定屏幕以及使用 OPENCV 进行其他操作! 644 | - [guoxbin/dtool](https://github.com/guoxbin/dtool) — 一个有用的命令行工具集合,用于协助开发,包括转换、编解码器、散列、加密等. 645 | - [nomino](https://github.com/yaa110/nomino) — 开发人员批量重命名实用程序 646 | - [barberousse](https://github.com/zeapo/barberousse) — AWS Secrets Manager 编辑器 647 | - [vamolessa/verco](https://github.com/vamolessa/verco) [[verco](https://crates.io/crates/verco)] — 一个简单的 Git/Hg tui 客户端,专注于键盘快捷键 648 | 649 | ### 视频 650 | 651 | - [Phate6660/rsmpv](https://github.com/Phate6660/rsmpv) — MPV 控制器,需要在 MPV 中启用 IPC. 652 | - [tgotwig/vidmerger](https://github.com/tgotwig/vidmerger) — ffmpeg 的包装器,可简化多个视频的合并 653 | - [xiph/rav1e](https://github.com/xiph/rav1e) — 最快、最安全的 AV1 编码器. 654 | - [yuvadm/slingr](https://github.com/yuvadm/slingr) — 一个简单的 CLI,用于通过本地网络将媒体文件流式传输到 UPnP 媒体渲染器 655 | - [yuvadm/streamlib](https://github.com/streamlib/streamlib) — 从命令行播放您最喜欢的实时视频和音频流 656 | 657 | ### 虚拟化技术 658 | 659 | - [firecracker-microvm/firecracker](https://github.com/firecracker-microvm/firecracker) — 用于容器工作负载的轻量级虚拟机 [Firecracker Microvm](https://firecracker-microvm.github.io/) 660 | - [oracle/railcar](https://github.com/oracle/railcar) — Rust 中类似 Docker 的容器 OCI 运行时实现 661 | - [tailhook/vagga](https://github.com/tailhook/vagga) — 一个没有守护进程的容器化工具 662 | 663 | ### Web 664 | 665 | - [Plume-org/Plume](https://github.com/Plume-org/Plume) — ActivityPub 联合博客应用程序 666 | - [LemmyNet/lemmy](https://github.com/LemmyNet/lemmy) — 联邦宇宙的链接聚合器 / reddit 克隆 667 | 668 | ### Web Servers 669 | 670 | - [mufeedvh/binserve](https://github.com/mufeedvh/binserve) — 极快的静态 Web 服务器,在单个二进制文件中具有路由、模板和安全性,您可以使用零代码进行设置 671 | - [thecoshman/http](https://github.com/thecoshman/http) — 请托管这些东西 — 一个基本的 http 服务器,用于快速简单地托管文件夹 672 | - [svenstaro/miniserve](https://github.com/svenstaro/miniserve) — 一个小型的、自包含的跨平台 CLI 工具,允许您只获取二进制文件并通过 HTTP 提供一些文件 673 | - [TheWaWaR/simple-http-server](https://github.com/TheWaWaR/simple-http-server) — 简单的静态 http 服务器 674 | - [wyhaya/see](https://github.com/wyhaya/see) — 静态 HTTP 文件服务器 675 | - [ronanyeah/rust-hasura](https://github.com/ronanyeah/rust-hasura) — Rust GraphQL 服务器如何用作远程模式的演示 [Hasura](https://hasura.io/) 676 | 677 | ## 开发工具 678 | 679 | - [clippy](https://crates.io/crates/clippy) 680 | - [clog-tool/clog-cli](https://github.com/clog-tool/clog-cli) — 从 git 元数据生成变更日志 ([conventional changelog](https://blog.thoughtram.io/announcements/tools/2014/09/18/announcing-clog-a-conventional-changelog-generator-for-the-rest-of-us.html)) 681 | - [dan-t/rusty-tags](https://github.com/dan-t/rusty-tags) — 为货物项目及其所有依赖项创建 ctags/etags 682 | - [datanymizer/datanymizer](https://github.com/datanymizer/datanymizer) - 强大的数据库匿名器,具有灵活的规则 683 | - [delta](https://crates.io/crates/git-delta) — git 和 diff 输出的语法高亮器 684 | - [dotenv-linter](https://github.com/dotenv-linter/dotenv-linter) — 用于 `.env` 文件的 Linter[frewsxcv/crate-deps](https://github.com/frewsxcv/crate-deps) — 为 crates.io 上托管的 crate 生成依赖图的图像 685 | - [geiger](https://github.com/rust-secure-code/cargo-geiger) — 一个程序,列出与在 Rust crate 及其所有依赖项中使用不安全 Rust 代码相关的统计信息m/cargo-geiger/cargo-geiger/_build/latest?definitionId=1&branchName=master) 686 | - [git-journal](https://github.com/saschagrunert/git-journal/) — Git 提交消息和变更日志生成框架 687 | - [gstats](https://github.com/boonshift/gstats/) — 用于打印当前目录下所有 git 存储库的开发人员方便摘要的命令行工具 688 | - [rust-lang/rustfix](https://github.com/rust-lang/rustfix) — 自动应用 rustc 提出的建议 689 | - [just](https://github.com/casey/just) — 用于特定项目任务的便捷命令运行器 690 | - [mask](https://github.com/jakedeichert/mask) — 由一个简单的 Markdown 文件定义的 CLI 任务运行器 691 | - [Module Linker](https://github.com/fiatjaf/module-linker) —在 GitHub 的 `mod`、`use` 和 `extern crate` 语句中添加 `` 链接到引用的扩展. 692 | - [ptags](https://github.com/dalance/ptags) — git 存储库的并行通用 ctags 包装器 693 | - [Racer](https://github.com/racer-rust/racer) — Rust 的代码完成 694 | - [rustfmt](https://github.com/rust-lang/rustfmt) — Rust 代码格式化程序 695 | - [Rustup](https://github.com/rust-lang/rustup) — Rust 工具链安装程序 696 | - [Rust Language Server](https://github.com/rust-lang/rls) — 在后台运行的服务器,为 IDE、编辑器和其他工具提供有关 Rust 程序的信息 697 | - [Rust Regex Playground](https://2fd.github.io/rust-regex-playground/#method=find®ex=\w%2B&text=abc) — 评估 Rust 正则表达式的 Web 工具 698 | - [Rust Search Extension](https://github.com/huhu/rust-search-extension) — 一个方便的浏览器扩展,用于在地址栏(多功能框)中搜索 crate 和文档. 699 | - [artifact](https://github.com/vitiral/artifact) — 为开发人员制作的设计文档工具 700 | - [semantic-rs](https://github.com/semantic-rs/semantic-rs) — 自动 crate 发布 701 | - [fw](https://github.com/brocode/fw) — 工作空间生产力助推器 702 | - [tinyrick](https://github.com/mcandre/tinyrick) 一个基本的任务依赖工具,强调 Rust 功能而不是原始 shell 命令. 703 | - [scriptisto](https://github.com/igor-petruk/scriptisto) 一种与语言无关的 “shebang 解释器”,它使您能够用编译语言编写一个文件脚本. 704 | 705 | ### 系统编译 706 | 707 | - [Cargo](https://crates.io/) — Rust 包管理器 708 | - [cargo-benchcmp](https://crates.io/crates/cargo-benchcmp) — 比较 Rust 微基准的实用程序 709 | - [cargo-bitbake](https://crates.io/crates/cargo-bitbake) — 一个货物扩展,可以利用 meta-rust 中的类生成 BitBake 配方 710 | - [cargo-cache](https://crates.io/crates/cargo-cache) - 检查 / 管理 / 清理你的货物缓存(`~/.cargo/`/`${CARGO_HOME}`),打印尺寸等 711 | - [cargo-check](https://crates.io/crates/cargo-check) — `cargo rustc -- -Zno-trans` 的包装器,如果您只需要正确性检查,它可以帮助运行更快的编译 712 | - [cargo-count](https://crates.io/crates/cargo-count) — 列出有关货物项目的源代码计数和详细信息,包括不安全统计数据 713 | - [cargo-deb](https://crates.io/crates/cargo-deb) — 生成二进制 Debian 软件包 714 | - [cargo-deps](https://crates.io/crates/cargo-deps) — 构建 Rust 项目的依赖图 715 | - [cargo-do](https://crates.io/crates/cargo-do) — 连续运行多个货物命令 716 | - [cargo-ebuild](https://crates.io/crates/cargo-ebuild) — 可以使用树内 eclasses 生成 ebuild 的货物扩展 717 | - [cargo-edit](https://crates.io/crates/cargo-edit) — 允许您通过从命令行读取 / 写入 Cargo.toml 文件来添加和列出依赖项 718 | - [cargo-generate](https://github.com/cargo-generate/cargo-generate) 通过利用预先存在的 git 存储库作为模板来生成 Rust 项目. 719 | - [cargo-get](https://crates.io/crates/cargo-get) - Cargo 插件可以轻松地从 Cargo.toml 文件中查询信息 720 | - [cargo-graph](https://crates.io/crates/cargo-graph) — 更新了具有附加功能的 `cargo-dot` 分支. 未维护,请参阅`cargo-deps` 721 | - [cargo-info](https://crates.io/crates/cargo-info) — 从命令行查询 crates.io 以获取 crates 详细信息 722 | - [cargo-license](https://crates.io/crates/cargo-license) — 一个货物子命令,用于快速查看所有依赖项的许可证. 723 | - [cargo-make](https://crates.io/crates/cargo-make) — Rust 任务运行器和构建工具. 724 | - [cargo-modules](https://crates.io/crates/cargo-modules) — 一个货物插件,用于显示板条箱模块的树状概览. 725 | - [cargo-multi](https://crates.io/crates/cargo-multi) — 在多个板条箱上运行指定的货物命令 726 | - [cargo-outdated](https://crates.io/crates/cargo-outdated) — 在新版本的 Rust 依赖项可用或过时时显示 727 | - [cargo-release](https://crates.io/crates/cargo-release) — 用于发布 git 管理的货物项目、构建、标记、发布、文档和推送的工具 728 | - [cargo-script](https://crates.io/crates/cargo-script) — 让人们快速、轻松地运行 Rust “脚本”,它可以利用 Cargo 的包生态系统 729 | - [cargo-testify](https://crates.io/crates/cargo-testify) — 监视文件更改、运行测试并通过友好的操作系统通知通知结果 730 | - [cargo-tree](https://github.com/sfackler/cargo-tree) – Cargo 子命令,以树状格式可视化 crate 的依赖关系图 731 | - [cargo-update](https://crates.io/crates/cargo-update) — 用于检查和应用更新已安装的可执行文件的货物子命令 732 | - [cargo-watch](https://crates.io/crates/cargo-watch) — 货物在源更改时编译项目的实用程序 733 | - [liuchong/cargo-x](https://github.com/liuchong/cargo-x) ——一个非常简单的第三方 cargo 子命令来执行自定义命令 734 | - [dtolnay/cargo-expand](https://github.com/dtolnay/cargo-expand) — 扩展源代码中的宏 735 | - [Devolutions/CMakeRust](https://github.com/Devolutions/CMakeRust) — 用于将 Rust 库集成到 CMake 项目中 736 | - [SiegeLord/RustCMake](https://github.com/SiegeLord/RustCMake) — 一个示例项目,展示了 CMake 与 Rust 的使用 737 | - [icepuma/rust-action](https://github.com/icepuma/rust-action) ——Rust github 动作 738 | - [peaceiris/actions-mdbook](https://github.com/peaceiris/actions-mdbook) — mdBook 的 GitHub 操作 739 | - GitHub 网络钩子 740 | - [snare](https://tratt.net/laurie/src/snare/) — GitHub webhooks 运行器守护进程 741 | - 网络包 742 | - [mxseev/rust-loader](https://github.com/mxseev/rust-loader) — Webpack Rust 加载器 (wasm) 743 | 744 | ### 调试 745 | 746 | - [rust-gdb](https://github.com/rust-lang/rust/blob/master/src/etc/rust-gdb) 747 | - [gdbgui](https://github.com/cs01/gdbgui) — 基于浏览器的 gdb 前端,用于调试 C、C++、Rust 和 Go. 748 | - [lldb_batchmode.py](https://github.com/rust-lang/rust/blob/master/src/etc/lldb_batchmode.py) — 允许以类似于 GDB 的批处理模式的方式使用 LLDB. 749 | - [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) — 一个 LLDB 扩展 [Visual Studio Code](https://code.visualstudio.com/). 750 | 751 | ### 部署 752 | 753 | - [emk/rust-musl-builder](https://github.com/emk/rust-musl-builder) — 用于使用 musl-libc 和 musl-gcc 编译静态 Rust 二进制文件的 Docker 映像,以及有用的 C 库的静态版本 754 | - [kpcyrd/mini-docker-rust](https://github.com/kpcyrd/mini-docker-rust) — 一个非常小的 Rust docker 镜像的示例项目 755 | - [liuchong/docker-rustup](https://github.com/liuchong/docker-rustup) — 多版本(使用 musl 工具)Rust Docker 镜像 756 | - [messense/rust-musl-cross](https://github.com/messense/rust-musl-cross) — 使用 musl-cross 编译静态 Rust 二进制文件的 Docker 镜像 757 | - [rust-lang-nursery/docker-rust](https://github.com/rust-lang/docker-rust) — 官方 Rust Docker 镜像 758 | - [wasm-template-rust](https://github.com/sn99/wasm-template-rust) — Rust 发布到 gh-pages 的 wasm 模板,无需 npm-deploy 759 | - [DenisKolodin/rust-app-engine](https://github.com/DenisKolodin/rust-app-engine) — App Engine Rust 样板 760 | - [emk/heroku-buildpack-rust](https://github.com/emk/heroku-buildpack-rust) — Heroku 上的 Rust 应用程序构建包 761 | 762 | ### 嵌入式 763 | 764 | - [japaric/rust-cross](https://github.com/japaric/rust-cross) ——关于交叉编译 Rust 程序你需要知道的一切 765 | - [japaric/xargo](https://github.com/japaric/xargo) — 轻松地将 Rust 程序交叉编译到自定义的裸机目标,如 ARM Cortex-M 766 | - [Ogeon/rust-on-raspberry-pi](https://github.com/Ogeon/rust-on-raspberry-pi) — 有关如何为 Raspberry Pi 交叉编译 Rust 项目的说明. * 阿杜诺 767 | - [avr-rust/ruduino](https://github.com/avr-rust/ruduino) `t Arduino Uno 的可重用组件. 768 | 769 | ### FFI 770 | 771 | 也可以看看 [Foreign Function Interface](https://doc.rust-lang.org/book/first-edition/ffi.html), [The Rust FFI Omnibus](http://jakegoulding.com/rust-ffi-omnibus/) (使用其他语言用 Rust 编写的代码的示例集合)和 [FFI examples written in Rust](https://github.com/alexcrichton/rust-ffi-examples). 772 | 773 | - [rlhunt/cbindgen](https://github.com/eqrion/cbindgen) — 从 Rust 源文件生成 C 头文件. 在 Gecko 中用于 WebRender 774 | - [Sean1708/rusty-cheddar](https://github.com/Sean1708/rusty-cheddar) — 从 Rust 源文件生成 C 头文件 775 | - [rust-lang/rust-bindgen](https://github.com/rust-lang/rust-bindgen) — Rust 绑定生成器 776 | - [dtolnay/cxx](https://github.com/dtolnay/cxx) — Rust 和 C++ 之间的安全互操作 777 | - [rust-cpp](https://crates.io/crates/cpp) - 直接在 Rust 中嵌入 C++ 代码 778 | - [rusterlium/rustler](https://github.com/rusterlium/rustler) — 用于创建 Erlang NIF 函数的安全 Rust 桥 779 | - [mgattozzi/curryrs](https://github.com/mgattozzi/curryrs) — 弥合 Haskell 和 Rust 之间的差距 780 | - [mgattozzi/haskellrs](https://github.com/mgattozzi/haskellrs) — Haskell FFI 示例中的 Rust 781 | - [mgattozzi/rushs](https://github.com/mgattozzi/rushs) — Rust FFI 示例中的 Haskell 782 | - [j4rs](https://crates.io/crates/j4rs) — 使用 Rust 中的 Java 783 | - [bennettanderson/rjni](https://github.com/benanders/rjni) — 使用 Rust 中的 Java 784 | - [drrb/java-rust-example](https://github.com/drrb/java-rust-example) — 使用 Java 中的 Rust 785 | - [jni](https://crates.io/crates/jni) — 使用 Java 中的 Rust 786 | - [jni-sys](https://crates.io/crates/jni-sys) — 对应于 jni.h 的 Rust 定义 787 | - [rucaja](https://crates.io/crates/rucaja) — 使用 Rust 中的 Java 788 | - [rawrafox/rust-jdbc](https://github.com/rawrafox/rust-jdbc) — 使用来自 Rust 的 JDBC 789 | - [jcmoyer/rust-lua53](https://github.com/jcmoyer/rust-lua53) — 用于 Rust 的 Lua 5.3 绑定 790 | - [lilyball/rust-lua](https://github.com/lilyball/rust-lua) — Safe Rust bindings to Lua 5.1 791 | - [tickbh/td_rlua](https://github.com/tickbh/td_rlua) — Rust 的零成本高级 lua 5.3 包装器 792 | - [tomaka/hlua](https://github.com/tomaka/hlua) - 与 Lua 交互的 Rust 库 793 | - [anima-engine/mrusty](https://github.com/anima-engine/mrusty) — Rust 的 mruby 安全绑定 794 | - [neon-bindings/neon](https://github.com/neon-bindings/neon) — Rust 绑定,用于编写安全且快速的原生 Node.js 模块 795 | - [infinyon/node-bindgen](https://github.com/infinyon/node-bindgen) - 使用 Rust 生成 nodejs 模块的简单方法 * 目标 - C 796 | - [SSheldon/rust-objc](https://github.com/SSheldon/rust-objc) — Rust 的 Objective-C 运行时绑定和包装器 797 | - [vickenty/mi-rust](https://github.com/vickenty/mi-rust) — 添加对 M::I 的支持,以使用 Cargo 构建模块 798 | - [vickenty/perl-xs](https://github.com/vickenty/perl-xs) — 使用 Rust 创建 Perl XS 模块 799 | - [getsentry/milksnake](https://github.com/getsentry/milksnake) — python setuptools 的扩展,它允许您以可想象的最便携的方式在 Python 轮子中分发动态链接库. 800 | - [dgrunwald/rust-cpython](https://github.com/dgrunwald/rust-cpython) — Python 绑定 801 | - [PyO3/PyO3](https://github.com/PyO3/PyO3) — Python 解释器的 Rust 绑定 802 | - [d-unseductable/ruru](https://github.com/d-unseductable/ruru) — 用 Rust 编写的原生 Ruby 扩展 803 | - [danielpclark/rutie](https://github.com/danielpclark/rutie) — 用 Rust 编写的原生 Ruby 扩展,反之亦然 804 | - [tildeio/helix](https://github.com/tildeio/helix) — 用 Rust 编写 Ruby 类 805 | - [rustwasm/wasm-pack](https://github.com/rustwasm/wasm-pack) — 打包 wasm 并发布到 npm! 806 | - [rustwasm/wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) — 一个促进 wasm 模块和 JS 之间高级交互的项目. 807 | - [rhysd/wain](https://github.com/rhysd/wain) - wain:在 Safe Rust 中从零开始的 WebAssembly 解释器,零依赖 808 | 809 | ### IDEs 810 | 811 | 也可以看看 [Are we (I)DE yet?](https://areweideyet.com/) 和 [Rust Tools](https://www.rust-lang.org/tools). 812 | 813 | - Atom 814 | 815 | - [zargony/atom-language-rust](https://github.com/zargony/atom-language-rust) 816 | - [rust-lang/atom-ide-rust](https://github.com/rust-lang/atom-ide-rust) — Rust IDE 对 Atom 的支持,由 Rust 语言服务器 (RLS) 提供支持 817 | 818 | - Eclipse 819 | 820 | - [Eclipse Corrosion](https://github.com/eclipse/corrosion) 821 | - [RustDT](https://github.com/RustDT/RustDT) 822 | 823 | - Emacs 824 | 825 | - [rust-mode](https://github.com/rust-lang/rust-mode) — Rust 主要模式 826 | - [rustic](https://github.com/brotzeit/rustic) - Emacs 的 Rust 开发环境 827 | - [flycheck-rust](https://github.com/flycheck/flycheck-rust) — Rust 支持 [Flycheck](https://github.com/flycheck/flycheck) 828 | - [emacs-racer](https://github.com/racer-rust/emacs-racer) — 自动完成(另见 [company](https://company-mode.github.io/) 和 [auto-complete](https://github.com/auto-complete/auto-complete)) 829 | 830 | - [gitpod.io](https://gitpod.io/) — 基于 Rust 语言服务器的具有完整 Rust 支持的在线 IDE 831 | 832 | - [gnome-builder](https://wiki.gnome.org/Apps/Builder) 自版本 3.22.2 起原生支持 Rust 和 Cargo 833 | 834 | - Kakoune 835 | 836 | - [kak-lsp/kak-lsp](https://github.com/kak-lsp/kak-lsp/) — [LSP](https://microsoft.github.io/language-server-protocol/) 客户. 在 Rust 中实现并支持 rls 开箱即用. 837 | 838 | - NetBeans 839 | 840 | - [drrb/rust-netbeans](https://github.com/drrb/rust-netbeans) 841 | 842 | - IntelliJ 843 | 844 | - [intellij-rust/intellij-rust](https://github.com/intellij-rust/intellij-rust) 845 | - [intellij-rust/intellij-toml](https://github.com/intellij-rust/intellij-toml) — 基本的 Toml 支持 846 | 847 | - [Ride](https://github.com/madeso/ride) 848 | 849 | - [SolidOak](https://github.com/oakes/SolidOak) — 一个简单的 Rust IDE,基于 GTK+ 和 [Neovim](https://github.com/neovim/neovim) 850 | 851 | - Sublime Text 852 | 853 | - [rust-lang/rust-enhanced](https://github.com/rust-lang/rust-enhanced) — 官方 Rust 包 854 | - [sublimehq/packages](https://github.com/sublimehq/Packages/tree/master/Rust) — 原生 Sublime 支持(已安装) 855 | 856 | - Vim 857 | 858 | — 无处不在的文本编辑器 859 | 860 | - [rust.vim](https://github.com/rust-lang/rust.vim) — 提供文件检测、语法高亮、格式化、Syntastic 集成等. 861 | - [vim-cargo](https://github.com/timonv/vim-cargo) — 命令绑定以从 vim 快速运行货物. 862 | - [vim-racer](https://github.com/racer-rust/vim-racer) — 允许 vim 使用 [Racer](https://github.com/racer-rust/racer) 用于 Rust 代码完成和导航. 863 | - [autozimu/LanguageClient-neovim](https://github.com/autozimu/LanguageClient-neovim) — [LSP](https://microsoft.github.io/language-server-protocol/) 客户. 在 Rust 中实现并支持 rls 开箱即用 864 | 865 | - 视觉工作室 866 | 867 | - [PistonDevelopers/VisualRust](https://github.com/PistonDevelopers/VisualRust) — Rust 的 Visual Studio 扩展 868 | - [dgriffen/rls-vs2017](https://github.com/ZoeyR/rls-vs2017) — 对 Visual Studio 2017 预览版的 Rust 支持 869 | 870 | - Visual Studio Code 871 | 872 | - [rust-lang/rls-vscode](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust) — 对 Visual Studio Code 的 Rust 支持 873 | - [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer) — RLS 的替代 Rust 语言服务器 874 | - [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) — 一个 LLDB 扩展 875 | - [crates](https://github.com/serayuzgur/crates) — crates 是 crates.io 依赖项的扩展. 876 | 877 | ### 图像识别 878 | 879 | - [sfikas/rusteval](https://github.com/sfikas/rusteval) — 用于评估检索算法输出的工具 880 | 881 | ### 分析 882 | 883 | - [bheisler/criterion.rs](https://github.com/bheisler/criterion.rs) — 统计驱动的 Rust 基准测试库 884 | - [sharkdp/hyperfine](https://github.com/sharkdp/hyperfine) — 命令行基准测试工具 885 | - [performancecopilot/hornet](https://github.com/performancecopilot/hornet) — Performance Co-Pilot 内存映射值检测库 886 | - [koute/memory-profiler](https://github.com/koute/memory-profiler) — Linux 的内存分析器 887 | - [ellisonch/rust-stopwatch](https://github.com/ellisonch/rust-stopwatch) — 一个秒表库 888 | - [mrhooray/torch](https://github.com/mrhooray/torch) — 根据 DWARF 调试信息生成 FlameGraphs 889 | - [llogiq/flame](https://github.com/llogiq/flame) 890 | 891 | ### Services 892 | 893 | - [deps.rs](https://github.com/deps-rs/deps.rs) — 检测过时或不安全的依赖项 894 | - [docs.rs](https://docs.rs/) — 自动生成 crate 文档 895 | 896 | ### 静态分析 897 | 898 | - [facebookexperimental/MIRAI](https://github.com/facebookexperimental/mirai) — 一个在 Rust 的中级中间表示 (MIR) 上运行的抽象解释器 899 | - [static_assertions](https://crates.io/crates/static_assertions) — 编译时断言以确保满足不变量 900 | 901 | ### 测试 902 | 903 | - [laboratory](https://crates.io/crates/laboratory) — 一个简单、富有表现力的 Rust 单元测试框架 904 | - [cucumber-rust](https://crates.io/crates/cucumber-rust) — Rust 的 Cucumber 测试框架的实现. 905 | - [demonstrate](https://crates.io/crates/demonstrate) — 声明式测试框架 906 | - [httpmock](https://github.com/alexliesenfeld/httpmock) — HTTP 模拟 907 | - [mockiato](https://crates.io/crates/mockiato) — 一个严格但友好的 Rust 2018 模拟库 908 | - [mutagen](https://crates.io/crates/mutagen) — 一个源级变异测试框架(仅限每晚) 909 | - [AlKass/polish](https://github.com/AlKass/polish) — 迷你测试 / 测试驱动框架 910 | - [proptest](https://crates.io/crates/proptest) — 受启发的属性测试框架 [Hypothesis](https://hypothesis.works/) Python 框架 911 | - [quickcheck](https://crates.io/crates/quickcheck) — 一个 Rust 实现 [QuickCheck](https://wiki.haskell.org/Introduction_to_QuickCheck1) 912 | - [mockito](https://crates.io/crates/mockito) — HTTP 模拟 913 | - [speculate](https://crates.io/crates/speculate) — 一个 RSpec 启发了 Rust 的最小测试框架 914 | - [rstest](https://crates.io/crates/rstest) — Rust 的基于夹具的测试框架 915 | - [ruspec](https://crates.io/crates/ruspec) — 像 Rspec 测试框架一样用 Rust 编写 916 | - [rust-fuzz/afl.rs](https://github.com/rust-fuzz/afl.rs) — 一个 Rust 模糊器,使用 [AFL](https://lcamtuf.coredump.cx/afl/) 917 | - [tarpaulin](https://crates.io/crates/cargo-tarpaulin) — 为 Rust 设计的代码覆盖率工具 918 | - [trust](https://github.com/japaric/trust) — Travis CI 和 AppVeyor 模板,用于在 5 种架构上测试您的 Rust crate 并发布其适用于 Linux、macOS 和 Windows 的二进制版本 919 | - [fake-rs](https://github.com/cksac/fake-rs) — 生成假数据的库 920 | - [goldenfile](https://github.com/calder/rust-goldenfile) - 一个为 Goldenfile 测试提供简单 API 的库. 921 | - [cargo-dinghy](https://crates.io/crates/cargo-dinghy/) - 简化在智能手机和其他小型处理器设备上运行库测试和工作台的货物扩展. 922 | 923 | ### 翻译器 924 | 925 | - [immunant/c2rust](https://github.com/immunant/c2rust) — 在 Clang/LLVM 之上构建的 C 到 Rust 翻译器和交叉检查器. 926 | - [jameysharp/corrode](https://github.com/jameysharp/corrode) — 用 Haskell 编写的 AC 到 Rust 翻译器. 927 | 928 | ## 收集系统信息 929 | 930 | - [Phate6660/nixinfo](https://github.com/Phate6660/nixinfo) [[crate](https://crates.io/crates/nixinfo)] — 一个用于收集系统信息(如 CPU、发行版、环境、内核等)的 lib crate. 931 | 932 | # 🐂 大牛语录 933 | 934 | ### Matthieum: 935 | 936 | “Rust 使编写正确且可读的代码变得更容易,同时获得两者并非巧合。 937 | 938 | 所有权/借用机制(对生命周期、别名和可变性的严格控制)在生成的软件的数据流中强制执行某种简单性,您可以在其他编程语言中获得这种简单性,但通常不会,因为该语言更宽松你得到了一个更复杂的流程。 939 | 940 | 你是否曾经在 Java 中调试过 ConcurrentModificationException?当您修改正在迭代的容器时会发生这种情况。当您有一系列回调/观察者时,意外地有导致此异常的循环引用非常容易。在 Rust 中,要解决这种情况,你必须使用 RefCell 或等价物,它应该让您停下来。” 941 | 942 | 943 |
944 |
945 |

零领工作

946 | 947 | --- 948 | 949 | ##### 实时提供,每周发布北京,上海,广州,深圳,杭州,南京,合肥,武汉,长沙,重庆,成都,西安,厦门的c/c++,golang方向的招聘岗位信息。 包含校招,社招,实习岗位, 面经,八股,简历 950 | 951 | 零领工作 952 | 953 |
954 |
955 | 956 | 957 | 958 | 959 | 960 | -------------------------------------------------------------------------------- /Rust入门秘笈.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/Understanding_in_Rust/cc988526af94561eae32bd77ed194a608e8fd493/Rust入门秘笈.pdf -------------------------------------------------------------------------------- /入门秘笈/Rust Box.md: -------------------------------------------------------------------------------- 1 | # Rust Box 2 | 3 | `Box `是一个智慧指标,指向在型别为T的堆上分配的资料。允许将资料储存在堆而不是堆叠上。是一个拥有的指标。除了将资料储存在堆上之外,当`Box ` 4 | 5 | `Box ` 6 | `Box` 7 | `Box` 8 | 9 | 使用 主要是,下面通过一个简单的例子来理解这一点:`Box ` 10 | `Box ` 11 | 12 | ```rust 13 | fn main() 14 | { 15 | let a = Box :: new(1); 16 | print!("value of a is : {}",a); 17 | } 18 | ``` 19 | 20 | 执行上面范例程式码,得到以下结果 - 21 | 22 | ```shell 23 | value of a is : 1 24 | ``` 25 | 26 | 在上面的例子中,如果存取 当程式结束时,储存在堆叠中,它指向的资料储存在堆上。`a``1``Box``Box``Box``Box` 27 | 28 | 下面来看看上面例子的图解表示: 29 | 30 | ![img](https://tw511.com/upload/images/201910/20191014013950410.png) 31 | 32 | **Cons列表** 33 | 34 | - `Cons`代表「构造功能」。 35 | - `Cons`列表是一个资料结构,用于从两个引数构造一个新对,这对称为`List` 36 | - 假设有两个元素`x` `y` `cons` `cons 「x到y」` `x` `y` 37 | - `Cons`列表包含两个元素,即当前项和最后一项。由于`Nil` `Nil` 38 | 39 | 现在,建立包含`cons` 40 | 41 | ```rust 42 | enum List 43 | { 44 | cons(i32, List), 45 | Nil, 46 | } 47 | ``` 48 | 49 | 在上面的程式码中,建立了`List` `i32` `cons` 50 | 51 | 现在,在以下范例中使用上面的`List` 52 | 53 | ```rust 54 | enum List { 55 | Cons(i32, List), 56 | Nil, 57 | } 58 | use List::{Cons, Nil}; 59 | fn main() 60 | { 61 | let list = List::Cons(1,Cons(2,Cons(3,Nil))); 62 | for i in list.iter() 63 | { 64 | print!("{}",i); 65 | } 66 | } 67 | ``` 68 | 69 | 执行上范例程式码,得到以下结果 - 70 | 71 | ![img](https://tw511.com/upload/images/201910/20191014013951411.png) 72 | 73 | 在上面的范例中,Rust编译器丢掷错误「具有无限大小」,因为List型别包含递回的变体。因此,Rust无法找出储存List值所需的空间。使用`Box ` 74 | 75 | ## 使用`Box ` 76 | 77 | Rust无法确定储存递回资料型别需要多少空间。Rust编译器在前一种情况下显示错误: 78 | 79 | ```shell 80 | = help: insert indirection (e.g., a 'Box', 'Rc', or '&') at some point to make 'List' representable 81 | ``` 82 | 83 | 在上面的例子中,可以使用 指标的大小在程式执行期间不会改变。指标指向将储存在堆上而不是 指标可以直接放在`Box ` `Box ` `Box ` `Box ` `cons` `Box ` `cons` 84 | 85 | ![img](https://tw511.com/upload/images/201910/20191014013951412.png) 86 | 87 | 下面来看一个简单的例子 - 88 | 89 | ```rust 90 | #[derive(Debug)] 91 | enum List { 92 | Cons(i32, Box), 93 | Nil, 94 | } 95 | use List::{Cons, Nil}; 96 | fn main() 97 | { 98 | let list = Cons(1,Box::new(Cons(2,Box::new(Cons(3,Box::new(Nil)))))); 99 | 100 | print!("{:?}",list); 101 | 102 | } 103 | ``` 104 | 105 | 执行上面范例程式码,得到以输出结果如下 - 106 | ``` 107 | Cons(1, Cons(2, Cons(3, Nil))) 108 | ``` 109 | -------------------------------------------------------------------------------- /入门秘笈/Rust Deref trait.md: -------------------------------------------------------------------------------- 1 | # Rust Deref trait 2 | 3 | `Deref trait`用于自定义解除参照运算子( 如果实现 因此,在参照上工作的程式码也可以用在智慧指标上。`*` 4 | `Deref ` 5 | 6 | ## 常规参照 7 | 8 | 常规参照是一种指向某个值的指标,该值储存在其他地方。下面来看一个简单的例子来建立`i32` `this` 9 | 10 | ```rust 11 | fn main() 12 | { 13 | let a = 20; 14 | let b = &a; 15 | if a==*b 16 | { 17 | println!("a and *b are equal"); 18 | } 19 | 20 | else 21 | { 22 | println!("they are not equal"); 23 | } 24 | } 25 | ``` 26 | 27 | 执行上面范例程式码,得到以下结果 - 28 | 29 | ```shell 30 | a and *b are equal 31 | ``` 32 | 33 | 在上面的例子中,如果使用 因此,可以比较变数 如果使用`a` `i32` `20` `b` `a` `* b` `20` `a` `* b` `&b` `* b` 34 | 35 | ## `Box `作为参照 36 | 37 | `Box `指标可用作参照。 38 | 39 | 下面来看一个简单的例子: 40 | 41 | ```rust 42 | fn main() 43 | { 44 | let a = 11; 45 | let b = Box::new(a); 46 | print!("Value of *b is {}",*b); 47 | } 48 | ``` 49 | 50 | 输出结果如下所示 - 51 | 52 | ```shell 53 | Value of *b is 11 54 | ``` 55 | 56 | 在上面的范例中,它们之间的唯一区别是b包含指向资料的框,而不是通过使用`Box ` `&` 57 | 58 | ## 智慧指标作为参照 59 | 60 | 现在,建立类似于`Box ` 61 | 62 | `Box `可以定义为具有一个元素的元组结构,例如 建立元组结构后,在`MyBox ` 63 | `MyBox ` 64 | 65 | 下面来看一个简单的例子: 66 | 67 | ```rust 68 | struct MyBox(T); 69 | impl MyBox 70 | { 71 | fn example(y : T)->MyBox 72 | { 73 | MyBox(y) 74 | } 75 | } 76 | fn main() 77 | { 78 | let a = 8; 79 | let b = MyBox::example(a); 80 | print!("Value of *b is {}",*b); 81 | } 82 | ``` 83 | 84 | 执行上面范例程式码,得到以下结果 - 85 | 86 | ![img](https://tw511.com/upload/images/201910/20191014013953413.png) 87 | 88 | 在上面的例子中,建立了智慧指标 因此得出结论,无法取消类似于`b` `Box ` 89 | 90 | ## 实现Deref Trait 91 | 92 | - `Deref Trait`在标准库中定义,该库用于实现名为`deref` 93 | - `deref`方法借用`self` 94 | 95 | 下面来看一个简单的例子: 96 | 97 | ```rust 98 | struct MyBox 99 | { 100 | a : T, 101 | } 102 | use :: std::ops::Deref; 103 | impl Deref for MyBox 104 | { 105 | type Target = T; 106 | fn deref(&self) ->&T 107 | { 108 | &self.a 109 | } 110 | } 111 | fn main() 112 | { 113 | let b = MyBox{a : 10}; 114 | print!("{}",*(b.deref())); 115 | } 116 | ``` 117 | 118 | 执行上面范例程式码,得到以下结果 - 119 | 120 | ```shell 121 | 10 122 | ``` 123 | 124 | **程式说明** 125 | 126 | - `Deref trait`在`MyBox` 127 | - `Deref trait`实现`deref()` `deref()` `a` 128 | - `type Target = T;`是 关联型别用于宣告泛型型别引数。`Deref trait` 129 | - 建立了`MyBox` `b` 130 | - 通过使用`MyBox``b.deref()` `deref()` `deref()` 131 | 132 | ## Deref强制 133 | 134 | - `Deref`强制是将实现`Deref trait` `Deref` 135 | - `Deref`强制是对函式和方法的引数执行的。 136 | - 当将特定型别的参照传递给与函式定义中的引数型别不匹配的函式时,`Deref` 137 | 138 | 下面来看一个简单的例子: 139 | 140 | ```rust 141 | struct MyBox(T); 142 | use :: std::ops::Deref; 143 | impl MyBox 144 | { 145 | fn hello(x:T)->MyBox 146 | { 147 | MyBox(x) 148 | } 149 | } 150 | impl Deref for MyBox 151 | { 152 | type Target = T; 153 | fn deref(&self) ->&T 154 | { 155 | &self.0 156 | } 157 | } 158 | fn print(m : &i32) 159 | { 160 | print!("{}",m); 161 | } 162 | fn main() 163 | { 164 | let b = MyBox::hello(5); 165 | 166 | print(&b); 167 | } 168 | ``` 169 | 170 | 执行上面范例程式码,得到以下结果 - 171 | 172 | ``` 173 | 5 174 | ``` 175 | 176 | 在上面的例子中,使用引数 在这种情况下,实现`&b` `print(&b)` `&Box ` `Deref trait` `Deref` `&Box ` `&i32` 177 | 178 | ## Derif强制与可变性的相互作用 179 | 180 | 到目前为止,使用`Deref Trait` `*` `DerefMut Trait` `*` 181 | 182 | Rust在以下三种情况下执行`Deref` 183 | 184 | - 当T:`Deref ` `T` `U` `&T` `&U` 185 | - 当T:`DerefMut ` `T` `U` `&mut T` `&mut U` 186 | - 当T:`Deref ` `T` `U` `&mut T` `&U` 187 | -------------------------------------------------------------------------------- /入门秘笈/Rust Drop trait.md: -------------------------------------------------------------------------------- 1 | # Rust Drop trait 2 | 3 | `drop trait`用于在值超出范围时释放档案或网路连线等资源。 4 | `drop trait`用于释放`Box `指向的堆上的空间。 5 | `drop trait`用于实现`drop()`方法,方法该对`self`进行可变参照。 6 | 7 | 下面来看一个简单的例子: 8 | 9 | ```rust 10 | struct Example 11 | { 12 | a : i32, 13 | } 14 | impl Drop for Example 15 | { 16 | fn drop(&mut self) 17 | { 18 | println!("Dropping the instance of Example with data : {}", self.a); 19 | } 20 | } 21 | fn main() 22 | { 23 | let a1 = Example{a : 10}; 24 | let b1 = Example{a: 20}; 25 | println!("Instances of Example type are created"); 26 | } 27 | ``` 28 | 29 | 执行上面的示例程序码,得到以下结果 - 30 | 31 | ```shell 32 | Instances of Example type are created 33 | Dropping the instance of Example with data : 20 34 | Dropping the instance of Example with data : 10 35 | ``` 36 | 37 | **程式程式码说明** 38 | 39 | - 在类型`Example`上实现了`Drop trait`,并在`Drop trait`的实现中定义了`drop()`方法。 40 | - 在`main()`函式中,建立了式样的范例,`Example`并且在`main()`函式的范围,范例远处了。 41 | - 当范例移出作用域时,铁锈会隐式呼叫`drop()`方法来删除`Example`类型范例。首先,删除范例`b1`,然后删除范例`a1`。 42 | 43 | > **注意**:无需显式呼叫`drop()`方法。因此,可以说当超出范围时,锈蚀隐式呼叫`drop()`方法。 44 | 45 | #### 使用std::mem::drop删除删除值 46 | 47 | 有时,有必要在范围结束之前删除该值。如果想提前删除该值,则使用`std::mem::drop`函式来删除该值。 48 | 49 | 下面来看一个手动删除值的简单例子: 50 | 51 | ```rust 52 | struct Example 53 | { 54 | a : String, 55 | } 56 | impl Drop for Example 57 | { 58 | fn drop(&mut self) 59 | { 60 | println!("Dropping the instance of Example with data : {}", self.a); 61 | } 62 | } 63 | fn main() 64 | { 65 | let a1 = Example{a : String::from("Hello")}; 66 | a1.drop(); 67 | let b1 = Example{a: String::from("World")}; 68 | println!("Instances of Example type are created"); 69 | } 70 | ``` 71 | 72 | 执行上面的示例程序码,得到以下结果 - 73 | 74 | ![img](https://tw511.com/upload/images/201910/20191014013954414.png) 75 | 76 | 在上面的例子中,呼叫手动`drop()`方法。防锈编译器丢掷一个错误,显不允许式呼叫`drop()`方法。显不是式呼叫`drop()`方法,呼叫而是`std::mem::drop`函式在值超出范围之前删除它。 77 | 78 | `std::mem::drop`的函式语法与`Drop trait`中定义的`drop()`。函式不同`std::mem::drop`。函式包含作为引数传递的值,值该在超出范围之前将被删除 79 | 下面来看一个简单的例子: 80 | 81 | ```rust 82 | struct Example 83 | { 84 | a : String, 85 | } 86 | 87 | impl Drop for Example 88 | { 89 | fn drop(&mut self) 90 | { 91 | println!("Dropping the instance of Example with data : {}", self.a); 92 | } 93 | } 94 | 95 | fn main() 96 | { 97 | let a1 = Example{a : String::from("Hello")}; 98 | drop(a1); 99 | let b1 = Example{a: String::from("World")}; 100 | println!("Instances of Example type are created"); 101 | } 102 | ``` 103 | 104 | 执行上面的示例程序码,得到以下结果—— 105 | 106 | ```shell 107 | Dropping the instance of Example with data : Hello 108 | Instances of Example type are created 109 | Dropping the instance of Example with data : World 110 | ``` 111 | 112 | 在上面的例子中,通过在`drop(a1)`式中将例子`a1`作为引数传来的例子`a1`。 113 | -------------------------------------------------------------------------------- /入门秘笈/Rust Trait.md: -------------------------------------------------------------------------------- 1 | # Rust Trait 2 | 3 | Rust trait 是Rust语言的一个特性(性状),它描述了它可以提供的每种型别的功能。性状类似于其他语言中定义的介面的特征。性状是一种对方法签名进行分组以定义一组行为的方法。使用 4 | 5 | 6 | `trait` 7 | 8 | `trait`的语法: 9 | 10 | ```rust 11 | trait trait_name 12 | //body of the trait. 13 | ``` 14 | 15 | 在上面的例子中,宣告特征后跟特征(性状)名称。在大括号内,宣告方法签名以描述实现特征的型别的行为。 16 | 17 | 下面来看一个简单的例子: 18 | 19 | ```rust 20 | struct Triangle 21 | { 22 | base : f64, 23 | height : f64, 24 | } 25 | trait HasArea 26 | { 27 | fn area(&self)->f64; 28 | } 29 | 30 | impl HasArea for Triangle 31 | { 32 | fn area(&self)->f64 33 | { 34 | 0.5*(self.base*self.height) 35 | } 36 | } 37 | fn main() 38 | { 39 | let a = Triangle{base:10.5,height:17.4}; 40 | let triangle_area = a.area(); 41 | println!("Area of a triangle is {}",triangle_area); 42 | } 43 | ``` 44 | 45 | 执行上面范例程式码,得到以下结果 - 46 | 47 | ```shell 48 | Area of a triangle is 91.35 49 | ``` 50 | 51 | 在上面的例子中,宣告了一个 是在 通过使用结构的范例,即`HasArea` `area()` `HasArea` `Triangle` `a.area()` `area()` 52 | 53 | ## 性状作为引数 54 | 55 | 特征(性状)也可以用作许多不同型别的引数。 56 | 57 | 上面的例子实现了 可以定义呼叫`HasArea` `area()` `area()` `calculate_area()` `HasArea` `area()` 58 | 59 | 下面来来看看语法: 60 | 61 | ```rust 62 | fn calculate_area(item : impl HasArea) 63 | println!("Area of the triangle is : {}",item.area()); 64 | } 65 | ``` 66 | 67 | ## 性状限制了通用函式 68 | 69 | 性状很有用,因为它们描述了不同方法的行为。但是,通用函式不遵循此约束。通过一个简单的场景来理解这一点: 70 | 71 | ```rust 72 | fn calculate_area( item : T) 73 | println!(?Area of a triangle is {}?, item.area()); 74 | ``` 75 | 76 | 在上面的例子中,Rust编译器丢掷「没有找到型别为 如果将性状系结到泛型`T` `T` 77 | 78 | ```rust 79 | fn calculate_area (item : T) 80 | { 81 | println!("Area of a triangle is {} ",item.area()); 82 | } 83 | ``` 84 | 85 | 在上面的例子中,Rust编译器知道任何实现`` `T` `HasArea` `HasArea` `area()` 86 | 87 | 下面来看一个简单的例子: 88 | 89 | ```rust 90 | trait HasArea 91 | { 92 | fn area(&self)->f64; 93 | } 94 | struct Triangle 95 | { 96 | base : f64, 97 | height : f64, 98 | } 99 | 100 | impl HasArea for Triangle 101 | { 102 | fn area(&self)->f64 103 | { 104 | 0.5*(self.base*self.height) 105 | } 106 | } 107 | struct Square 108 | { 109 | side : f64, 110 | } 111 | 112 | impl HasArea for Square 113 | { 114 | fn area(&self)->f64 115 | { 116 | self.side*self.side 117 | } 118 | } 119 | fn calculate_area(item : T) 120 | { 121 | println!("Area is : {}",item.area()); 122 | } 123 | 124 | fn main() 125 | { 126 | let a = Triangle{base:10.5,height:17.4}; 127 | let b = Square{side : 4.5}; 128 | calculate_area(a); 129 | calculate_area(b); 130 | } 131 | ``` 132 | 133 | 执行上面范例程式码,得到以下结果 - 134 | 135 | ```shell 136 | Area is : 91.35 137 | Area is : 20.25 138 | ``` 139 | 140 | 在上面的例子中,`calculate_area()``T` 141 | 142 | ## 实施性状的规则 143 | 144 | 实现性状有两个限制: 145 | 146 | - 如果范围中未定义性状,则无法在任何资料型别上实现该性状。 147 | 148 | 下面来看一个简单的例子: 149 | 150 | ```rust 151 | use::std::fs::File; 152 | fn main() 153 | { 154 | let mut f = File::create("hello.txt"); 155 | let str = "Yiibai"; 156 | let result = f.write(str); 157 | } 158 | ``` 159 | 160 | 执行上面范例程式码,得到以下结果 - 161 | 162 | ```shell 163 | error : no method named 'write' found. 164 | let result = f.write(str); 165 | ``` 166 | 167 | 在上面的例子中,Rust编译器丢掷一个错误,即 因此,需要使用`"no method named 'write' found"` `use::std::fs::File;` `write()` `Write trait` 168 | 169 | - 正在实现的性状必须定义。例如:如果定义 但是,无法为型别`HasArea` `i32` `i32` `toString` 170 | 171 | ## 多个性状界限 172 | 173 | 使用`'+'` 174 | 175 | 如果想系结多个性状,可使用`+` 176 | 177 | 下面来看一个简单的例子: 178 | 179 | ```rust 180 | use std::fmt::{Debug, Display}; 181 | fn compare_prints(t: &T) 182 | { 183 | println!("Debug: '{:?}'", t); 184 | println!("Display: '{}'", t); 185 | } 186 | 187 | fn main() { 188 | let string = "Yiibai"; 189 | compare_prints(&string); 190 | } 191 | ``` 192 | 193 | 执行上面范例程式码,输出结果如下 - 194 | 195 | ```shell 196 | Debug: ' "Yiibai"' 197 | Display: ' Yiibai' 198 | ``` 199 | 200 | 在上面的范例中,`Display` `Debug` `+` `T` 201 | 202 | 使用`where` 203 | 204 | - 使用出现在括号`{` `where` 205 | - `where`子句也可以应用于任意型别。 206 | - 当使用`where` 207 | 208 | 如下程式码 - 209 | 210 | ```rust 211 | fn fun(t:T,v:V)->i32 212 | //block of code; 213 | ``` 214 | 215 | 在上述情况下使用`where` 216 | 217 | ```rust 218 | fn fun(t:T, v:V)->i32 219 | where T : Display+ Debug, 220 | V : Clone+ Debug 221 | 222 | //block of code; 223 | ``` 224 | 225 | 在上面的例子中,使用`where` 226 | 227 | 下面来看看一个简单的例子: 228 | 229 | ```rust 230 | trait Perimeter 231 | { 232 | fn a(&self)->f64; 233 | } 234 | struct Square 235 | { 236 | side : f64, 237 | } 238 | impl Perimeter for Square 239 | { 240 | fn a(&self)->f64 241 | { 242 | 4.0*self.side 243 | } 244 | } 245 | struct Rectangle 246 | { 247 | length : f64, 248 | breadth : f64, 249 | } 250 | impl Perimeter for Rectangle 251 | 252 | { 253 | fn a(&self)->f64 254 | { 255 | 2.0*(self.length+self.breadth) 256 | } 257 | } 258 | fn print_perimeter(s:Square,r:Rectangle) 259 | where Square : Perimeter, 260 | Rectangle : Perimeter 261 | { 262 | let r1 = s.a(); 263 | let r2 = r.a(); 264 | println!("Perimeter of a square is {}",r1); 265 | println!("Perimeter of a rectangle is {}",r2); 266 | } 267 | fn main() 268 | { 269 | let sq = Square{side : 6.2}; 270 | let rect = Rectangle{length : 3.2,breadth:5.6}; 271 | print_perimeter(sq,rect); 272 | } 273 | ``` 274 | 275 | 执行上面范例程式码,得到以下结果 - 276 | 277 | ```shell 278 | Perimeter of a square is 24.8 279 | Perimeter of a rectangle is 17.6 280 | ``` 281 | 282 | ## 预设方法 283 | 284 | 可以将预设方法新增到性状定义的方法定义为已知。范例程式码: 285 | 286 | ```rust 287 | trait Sample 288 | 289 | fn a(&self); 290 | fn b(&self) 291 | { 292 | println!("Print b"); 293 | } 294 | ``` 295 | 296 | 在上面的例子中,预设行为被新增到性状定义中。还可以覆盖预设行为。下面通过一个例子看看这个场景: 297 | 298 | ```rust 299 | trait Sample 300 | { 301 | fn a(&self); 302 | fn b(&self) 303 | { 304 | println!("Print b"); 305 | } 306 | } 307 | 308 | struct Example 309 | { 310 | a:i32, 311 | b:i32, 312 | } 313 | 314 | 315 | 316 | impl Sample for Example 317 | { 318 | fn a(&self) 319 | { 320 | println!("Value of a is {}",self.a); 321 | } 322 | 323 | fn b(&self) 324 | { 325 | println!("Value of b is {}",self.b); 326 | } 327 | } 328 | fn main() 329 | { 330 | let r = Example{a:5,b:7}; 331 | r.a(); 332 | r.b(); 333 | } 334 | ``` 335 | 336 | 执行上面范例程式码,得到以下结果 - 337 | 338 | ```shell 339 | Value of a is : 5 340 | Value of b is : 7 341 | ``` 342 | 343 | 在上面的例子中,因此得出结论,可覆盖性状中定义的方法。`b()` 344 | 345 | ## 继承 346 | 347 | 从另一个性状派生的性状称为继承。有时,有必要实现另一个性状的性状。如果想从'A'性状继承'B'性状,那么它看起来像: 348 | 349 | ```rust 350 | trait B : A; 351 | ``` 352 | 353 | 参考以下一段完整的程式码 - 354 | 355 | ```rust 356 | trait A 357 | { 358 | fn f(&self); 359 | } 360 | trait B : A 361 | { 362 | fn t(&self); 363 | } 364 | struct Example 365 | { 366 | first : String, 367 | second : String, 368 | } 369 | impl A for Example 370 | { 371 | fn f(&self) 372 | { 373 | 374 | print!("{} ",self.first); 375 | } 376 | 377 | } 378 | impl B for Example 379 | { 380 | fn t(&self) 381 | { 382 | print!("{}",self.second); 383 | } 384 | } 385 | fn main() 386 | { 387 | let s = Example{first:String::from("Yiibai"),second:String::from("tutorial")}; 388 | s.f(); 389 | s.t(); 390 | } 391 | ``` 392 | 393 | 执行上面范例程式码,得到以下结果 - 394 | 395 | ```shell 396 | Yiibai tutorial 397 | ``` 398 | 399 | 在上面的例子中,程式实现'B'性状。因此,它还需要实现'A'性状。如果程式没有实现'A'性状,则Rust编译器会丢掷错误。 400 | -------------------------------------------------------------------------------- /入门秘笈/Rust for回圈.md: -------------------------------------------------------------------------------- 1 | # Rust for回圈 2 | 3 | ``` 4 | for`回圈是条件回圈,即回圈执行特定次数。Rust语言中 执行`for``for 5 | ``` 6 | 7 | for回圈的语法 - 8 | 9 | ```rust 10 | for var in expression 11 | { 12 | //block statements 13 | } 14 | ``` 15 | 16 | 在上面的语法中,表示式可以转换为叠代器,叠代器遍历资料结构的元素。在每次叠代中,都从叠代器中获取值。当没有剩余值被提取时,回圈结束。 17 | 18 | 下面来看一个简单的例子。 19 | 20 | ```rust 21 | fn main() 22 | { 23 | 24 | for i in 1..11 25 | { 26 | print!("{} ",i); 27 | } 28 | } 29 | ``` 30 | 31 | 执行上面范例程式码,得到以下结果 - 32 | 33 | ```shell 34 | 1 2 3 4 5 6 7 8 9 10 35 | ``` 36 | 37 | 在上面的范例中,上限是不包含的,因此回圈将列印`1..11``1``10` 38 | 39 | 下面再来看一个简单的例子。 40 | 41 | ```rust 42 | fn main() 43 | { 44 | let mut result; 45 | for i in 1..11 46 | { 47 | result=2*i; 48 | println!("2*{}={}",i,result); 49 | } 50 | } 51 | ``` 52 | 53 | 执行上面范例程式码,得到以下结果 - 54 | 55 | ```shell 56 | 2*1=2 57 | 2*2=4 58 | 2*3=6 59 | 2*4=8 60 | 2*5=10 61 | 2*6=12 62 | 2*7=14 63 | 2*8=16 64 | 2*9=18 65 | 2*10=20 66 | ``` 67 | 68 | 在上面的例子中,`for``2` 69 | 70 | 下面来看另一个简单的例子。 71 | 72 | ```rust 73 | fn main(){ 74 | let fruits=["mango","apple","banana","litchi","watermelon"]; 75 | for a in fruits.iter() 76 | { 77 | print!("{} ",a); 78 | } 79 | } 80 | ``` 81 | 82 | 执行上面范例程式码,得到以下结果 - 83 | 84 | ``` 85 | mango apple banana litchi watermelon 86 | ``` 87 | 88 | 在上面的例子中,当它到达阵列的最后一个元素,那么回圈就结束了。`iter()``fruits` 89 | 90 | **while回圈和for回圈的区别:因此,可以说** 91 | `while``for``for` 92 | -------------------------------------------------------------------------------- /入门秘笈/Rust if in a let语句.md: -------------------------------------------------------------------------------- 1 | # Rust if in a let语句 2 | 3 | 在`let``if``if``let` 4 | 5 | **if in a let语法** 6 | 7 | ```rust 8 | Let variable_name= if condition{ 9 | //code blocks 10 | }else{ 11 | //code block 12 | } 13 | ``` 14 | 15 | 在上面的语法中,如果条件为真,则将`if``false``else` 16 | 17 | ![img](https://tw511.com/upload/images/201910/20191014013905375.png) 18 | 19 | **范例1** 20 | 21 | 下面来看一个简单的例子。 22 | 23 | ```rust 24 | fn main(){ 25 | 26 | let a=if true 27 | { 28 | 1 29 | } 30 | else 31 | { 32 | 2 33 | }; 34 | println!("value of a is: {}", a); 35 | } 36 | ``` 37 | 38 | 执行上面范例程式码,得到以下结果 - 39 | 40 | ```shell 41 | value of a is: 1 42 | ``` 43 | 44 | 在此范例中,条件为真。因此,现在,`a``if``a``1` 45 | 46 | 下面再来看一个另一个简单的例子。 47 | 48 | ```rust 49 | fn main(){ 50 | 51 | let a=if false 52 | { 53 | 9 54 | } 55 | else 56 | { 57 | "yiibai" 58 | }; 59 | println!("value of a is: {}", a); 60 | } 61 | ``` 62 | 63 | 执行上面范例程式码,得到以下结果 - 64 | 65 | ``` 66 | Some errors occurred:E0308 67 | ``` 68 | 69 | 在此范例中,因此,该程式丢掷错误,因为两个块都包含不同型别的值。`if``else` 70 | -------------------------------------------------------------------------------- /入门秘笈/Rust if let控制流程.md: -------------------------------------------------------------------------------- 1 | # Rust if let控制流程 2 | 3 | ``` 4 | if let`语法用于组合 运算子和`if``let``「match」``「if let」 5 | ``` 6 | 7 | **匹配运算子的范例** 8 | 9 | ```rust 10 | fn main() 11 | { 12 | let a = Some(5); 13 | match a { 14 | Some(5) => println!("five"), 15 | _ => (), 16 | }} 17 | ``` 18 | 19 | 执行上面范例程式码,得到以下结果 - 20 | 21 | ``` 22 | five 23 | ``` 24 | 25 | 在上面的范例中,匹配运算子在值等于 执行第一个变数后,如果使用`Some(5)``_ =>()``if``match` 26 | 27 | **if let范例** 28 | 29 | ```rust 30 | fn main() 31 | { 32 | let a=Some(3); 33 | if let Some(3)=a{ 34 | println!("three"); 35 | } 36 | } 37 | ``` 38 | 39 | 执行上面范例程式码,得到以下结果 - 40 | ```shell 41 | three 42 | ``` 43 | -------------------------------------------------------------------------------- /入门秘笈/Rust if语句.md: -------------------------------------------------------------------------------- 1 | # Rust if语句 2 | 3 | ``` 4 | if`语句确定条件是否为真。如果条件为`true``if``if 5 | ``` 6 | 7 | 表示`if` 8 | 9 | - if块 10 | - if-else块 11 | - if else-if阶梯块 12 | - 巢状if语句 13 | 14 | ## if语句 15 | 16 | `if`语句块的语法 - 17 | 18 | ```rust 19 | if condition 20 | { 21 | //block statements; 22 | } 23 | ``` 24 | 25 | 在上面的语法中,如果条件为真,则执行块语句,否则跳过`if` 26 | 27 | `if`语句的流程图 - 28 | 29 | ![img](https://tw511.com/upload/images/201910/20191014013903372.png) 30 | 31 | **范例:** 32 | `if` 33 | 34 | ```rust 35 | fn main(){ 36 | 37 | let a=1; 38 | if a==1 39 | { 40 | println!("a is equal to 1"); 41 | } 42 | } 43 | ``` 44 | 45 | 执行上面范例程式码,得到以下结果: 46 | 47 | ``` 48 | a is equal to 1 49 | ``` 50 | 51 | 在这个例子中,因此,`a``1``if``println!` 52 | 53 | ## if-else语句 54 | 55 | 如果条件为真,则执行 如果条件为假,则跳过`if``else``if``else` 56 | 57 | **if-else语句的语法** 58 | 59 | ``` 60 | if condition 61 | { 62 | //block statements 63 | }else{ 64 | //block statements 65 | } 66 | ``` 67 | 68 | **if-else的流程图** 69 | 70 | ![img](https://tw511.com/upload/images/201910/20191014013903373.png) 71 | 72 | 下面来看看一个`if-else` 73 | 74 | ```rust 75 | fn main() 76 | { 77 | let a=3; 78 | let b=4; 79 | if a>b 80 | { 81 | println!("a is greater than b"); 82 | } 83 | else 84 | { 85 | println!("a is smaller than b"); 86 | } 87 | } 88 | ``` 89 | 90 | 执行上面范例程式码,得到以下结果 - 91 | 92 | ``` 93 | a is smaller than b 94 | ``` 95 | 96 | 在该范例中,变数 因此,执行`a``3``a``b``else` 97 | 98 | ## else-if语句 99 | 100 | 如果要检查多个条件,则可使用`else-if` 101 | 102 | `else-if`语句的语法 - 103 | 104 | ``` 105 | if condition 1 106 | { 107 | //block statements 108 | }else if condition 2 109 | { 110 | //block statements 111 | } 112 | . 113 | . 114 | else{ 115 | //block statements 116 | } 117 | ``` 118 | 119 | 在上面的语法中,Rust为第一个真实条件执行块,当匹配到第一个真条件时,它就不会执行其余的块。 120 | 121 | `else if`语句块的流程图 - 122 | 123 | ![img](https://tw511.com/upload/images/201910/20191014013903374.png) 124 | 125 | 下面来看一个`else-if` 126 | 127 | ```rust 128 | fn main(){ 129 | 130 | let num= -5; 131 | if num>0 132 | { 133 | println!("number is greater than 0"); 134 | } 135 | else if num<0 136 | { 137 | println!("number is less than 0 "); 138 | } 139 | else 140 | { 141 | println!("number is not equal to 0"); 142 | } 143 | } 144 | ``` 145 | 146 | 执行上面范例程式码,得到以下结果 - 147 | 148 | ```shell 149 | number is less than 0 150 | ``` 151 | 152 | 在此范例中,变数 因此,`num``-5``num``0``else if` 153 | 154 | ## 巢状if-else语句 155 | 156 | 当 巢状`if-else``if``else``if-else` 157 | `if-else` 158 | 159 | ```rust 160 | if condition 1 161 | { 162 | // 巢狀if/else塊 163 | if condition 2 164 | { 165 | //block statements 166 | }else 167 | { 168 | //block statements 169 | } 170 | }else{ 171 | //block statements 172 | } 173 | ``` 174 | 175 | 下面来看一个巢状`if-else` 176 | 177 | ```rust 178 | fn main(){ 179 | 180 | let a=5; 181 | let b=6; 182 | if a!=b 183 | { 184 | if a>b 185 | { 186 | println!("a is greater than b"); 187 | }else{ 188 | println!("a is less than b"); 189 | } 190 | } 191 | 192 | else 193 | { 194 | println!("a is equal to b"); 195 | } 196 | } 197 | ``` 198 | 199 | 执行上面范例程式码,得到以下结果 - 200 | 201 | ```shell 202 | a is less than b 203 | ``` 204 | 205 | 在此范例中,因此,控制进入 因此,执行`a``b``if``a``b``else``if` 206 | -------------------------------------------------------------------------------- /入门秘笈/Rust loop回圈.md: -------------------------------------------------------------------------------- 1 | # Rust loop回圈 2 | 3 | 如果想要多次执行语句块,那么回圈概念就属于这个角色。回圈执行回圈体记忆体在的程式码直到结束,并从启动开始立即重新开始。 4 | 5 | Rust有三种回圈: 6 | 7 | - loop回圈 8 | - for回圈 9 | - while回圈 10 | 11 | ## loop回圈 12 | 13 | `loop`不是条件回圈。它是一个关键字,告诉Rust一次又一次地执行程式码块,直到除非明确地手动停止回圈。 14 | 15 | **loop回圈** 16 | 17 | ```rust 18 | loop{ 19 | //block statements 20 | } 21 | ``` 22 | 23 | 在上面的语法中,块语句被无限次执行。 24 | 25 | 回圈流程图: 26 | 27 | ![img](https://tw511.com/upload/images/201910/20191014013907376.png) 28 | 29 | 下面来看看一个无限回圈的简单例子 - 30 | 31 | ``` 32 | fn main(){ 33 | loop 34 | { 35 | println!("Hello Yiibai"); 36 | } 37 | } 38 | ``` 39 | 40 | 执行上面范例程式码,得到以下结果 - 41 | 42 | ``` 43 | Hello Yiibai 44 | Hello Yiibai 45 | Hello Yiibai 46 | Hello Yiibai 47 | . 48 | . 49 | . 50 | infinite times 51 | ``` 52 | 53 | 在这个例子中,「Hello Yiibai」字串一遍又一遍地列印,直到除非手动停止回圈。通常,「ctrl + c」命令用于从回圈终止。 54 | 55 | #### 回圈终止 56 | 57 | ``` 58 | break`关键字用于从回圈终止。如果未使用`break 59 | ``` 60 | 61 | 下面来看一个简单的例子 - 62 | 63 | ```rust 64 | fn main() 65 | 66 | let mut i=1; 67 | loop 68 | { 69 | println!("Hello Yiibai"); 70 | if i==7 71 | { 72 | break; 73 | } 74 | i+=1; 75 | } 76 | } 77 | ``` 78 | 79 | 执行上面范例程式码,得到以下结果 - 80 | 81 | ```shell 82 | Hello Yiibai 83 | Hello Yiibai 84 | Hello Yiibai 85 | Hello Yiibai 86 | Hello Yiibai 87 | Hello Yiibai 88 | Hello Yiibai 89 | ``` 90 | 91 | 在上面的例子中,`i` 92 | -------------------------------------------------------------------------------- /入门秘笈/Rust use关键字参照模组.md: -------------------------------------------------------------------------------- 1 | # Rust use关键字参照模组 2 | 3 | 当呼叫模组的函式时,需要指定完整的路径。 4 | 5 | 通过下面一个例子来理解这个概念: 6 | 7 | ```rust 8 | pub mod a 9 | { 10 | pub mod b 11 | { 12 | pub mod c 13 | { 14 | pub fn nested_modules() 15 | { 16 | println!("Nested Modules"); 17 | } 18 | } 19 | } 20 | } 21 | 22 | fn main() 23 | { 24 | a::b::c::nested_modules(); 25 | } 26 | ``` 27 | 28 | 执行上面范例程式码,得到以下结果 - 29 | 30 | ```shell 31 | Nested Modules 32 | ``` 33 | 34 | 在上面的例子中,通过指定完整路径来呼叫`nested_modules()``a::b::c::nested_modules()` 35 | 36 | ## use关键字 37 | 38 | 在上面的场景中,看到函式呼叫非常冗长。Rust中的 关键字只在范围中指定的那些模组。通过下面一个例子来理解这一点:`use``use` 39 | 40 | ```rust 41 | pub mod a 42 | { 43 | pub mod b 44 | { 45 | pub mod c 46 | { 47 | pub fn nested_modules() 48 | { 49 | println!("Nested Modules"); 50 | } 51 | } 52 | } 53 | } 54 | 55 | use a::b::c::nested_modules; 56 | fn main() 57 | { 58 | nested_modules(); 59 | } 60 | ``` 61 | 62 | 执行上面范例程式码,得到以下结果 - 63 | 64 | ```shell 65 | Nested Modules 66 | ``` 67 | 68 | 在上面的范例中,因此,可以直接呼叫函式,而不必在呼叫函式中包含模组。`use` 69 | 70 | 列举也是模组之类的名称空间的一种形式。因此,可以使用 在`use``use` 71 | 72 | 通过下面一个例子来理解: 73 | 74 | ```rust 75 | #[derive(Debug)] 76 | enum Flagcolor 77 | { 78 | Orange, 79 | White, 80 | Green, 81 | } 82 | use Flagcolor::{Orange,White,Green}; 83 | fn main() 84 | { 85 | let _o= Orange; 86 | let _w= White; 87 | let _g= Green; 88 | println!("{:?}",_o); 89 | println!("{:?}",_w); 90 | println!("{:?}",_g); 91 | } 92 | ``` 93 | 94 | 执行上面范例程式码,得到以下结果: 95 | 96 | ```shell 97 | orange 98 | white 99 | green 100 | ``` 101 | 102 | 在上面的范例中,因此,可以直接使用列举变体而不使用列举名称和名称空间说明符。`Flagcolor``use` 103 | 104 | ## 使用* 运算子 105 | 106 | ``` 107 | *`运算子用于将所有专案放入范围,这也称为 如果使用`glob``glob 108 | ``` 109 | 110 | 通过下面一个例子来理解这一点: 111 | 112 | ```rust 113 | #[derive(Debug)] 114 | enum Color 115 | { 116 | Red, 117 | Yellow, 118 | Green, 119 | Orange, 120 | } 121 | 122 | use Color::*; 123 | fn main() 124 | { 125 | let _red=Red; 126 | let _yellow=Yellow; 127 | let _green=Green; 128 | let _orange=Orange; 129 | println!("{:?}",_red); 130 | println!("{:?}",_yellow); 131 | println!("{:?}",_green); 132 | println!("{:?}",_orange); 133 | } 134 | ``` 135 | 136 | 执行上面范例程式码,得到以下结果 - 137 | 138 | ```shell 139 | Red 140 | Yellow 141 | Green 142 | Orange 143 | ``` 144 | 145 | 在上面的范例中,`*``use` 146 | 147 | ## 使用super 关键字 148 | 149 | `super`关键字用于从当前模组存取父模组,它使能够存取父模组的私有功能。 150 | 151 | ```rust 152 | mod a{ 153 | fn x() -> u8 { 154 | 5 155 | } 156 | 157 | pub mod example { 158 | use super::x; 159 | 160 | pub fn foo() { 161 | println!("{}",x()); 162 | } 163 | } 164 | } 165 | 166 | fn main() 167 | { 168 | a::example::foo(); 169 | } 170 | ``` 171 | 172 | 输出结果如下 - 173 | 174 | ```shell 175 | 2 176 | ``` 177 | 178 | 在上面的范例中,模组范例使用了参照其父模组的 由于这个原因,模组范例的`super``foo()``a` 179 | -------------------------------------------------------------------------------- /入门秘笈/Rust while回圈.md: -------------------------------------------------------------------------------- 1 | # Rust while回圈 2 | 3 | `while-loop`是一个条件回圈。当程式需要评估条件时,则使用条件回圈。当条件为真时,它执行回圈,否则它终止回圈。 4 | 5 | **while回圈的语法** 6 | 7 | ``` 8 | while condition 9 | //block statements; 10 | ``` 11 | 12 | 在上面的语法中,如果条件为真,则执行块语句,否则终止回圈。Rust提供了这个内建构造,可以与`while``loop``if``else``break` 13 | 14 | **while回圈流程图** 15 | 16 | ![img](https://tw511.com/upload/images/201910/20191014013910377.png) 17 | 18 | 下面来看一个简单的例子 - 19 | 20 | ```rust 21 | fn main() 22 | { 23 | let mut i=1; 24 | while i<=10 25 | { 26 | print!("{}", i); 27 | print!(" "); 28 | i=i+1; 29 | } 30 | } 31 | ``` 32 | 33 | 执行上面范例程式码,得到以下输出结果 - 34 | 35 | ``` 36 | 1 2 3 4 5 6 7 8 9 10 37 | ``` 38 | 39 | 在上面的例子中,回圈执行直到`i``i``while``i``10``10` 40 | 41 | 下面来看一个简单的例子 42 | 43 | ```rust 44 | fn main() 45 | { 46 | let array=[10,20,30,40,50,60]; 47 | let mut i=0; 48 | while i<6 49 | { 50 | print!("{}",array[i]); 51 | print!(" "); 52 | i=i+1; 53 | } 54 | } 55 | ``` 56 | 57 | 输出结果 - 58 | 59 | ``` 60 | 10 20 30 40 50 60 61 | ``` 62 | 63 | 在上面的范例中,使用`while` 64 | 65 | `while`回圈的缺点: 66 | 67 | - 如果索引长度不正确,回圈可能会导致问题。 68 | - 当编译器新增执行时程式码以通过此回圈对每次叠代执行条件检查时,它也很慢。 69 | -------------------------------------------------------------------------------- /入门秘笈/Rust不可恢复的错误.md: -------------------------------------------------------------------------------- 1 | # Rust不可恢复的错误 2 | 3 | 不可恢复的错误是检测到的错误,程式员无法处理它。当发生这种错误时,列印失败讯息。清理堆叠然后退出。`panic!``panic!``panic!` 4 | 5 | ![img](https://tw511.com/upload/images/201910/20191014013938396.png) 6 | 7 | **展开(Unwinding) 但是,展开过程需要大量工作。的替代方案是 中止(Aborting) 作业系统将删除资料。如果从展开切换到中止,那么需要新增以下语句:**`Unwinding` `Aborting` 8 | 9 | ```rust 10 | panic = 'abort'; 11 | ``` 12 | 13 | 下面来看一个`panic!` 14 | 15 | ```rust 16 | fn main() 17 | { 18 | panic!(?No such file exist?); 19 | } 20 | ``` 21 | 22 | 执行上面范例程式码,得到如下结果 - 23 | 24 | ![img](https://tw511.com/upload/images/201910/20191014013938397.png) 25 | 26 | 在上面的输出中,第一行显示错误讯息,它传达两个资讯,即 讯息是「没有这样的档案存在」 和 `panic` `panic` `error.rs:3:5` 27 | 28 | > 注意:一般来说,不实现`panic!` `panic!` 29 | 30 | ## panic!的好处 31 | 32 | Rust语言没有缓冲区重读问题。缓冲区重写是一种情况,当从缓冲区读取资料并且程式超出缓冲区时,即它读取相邻的储存器。这导致违反记忆体安全。 33 | 34 | 下面来看一个简单的例子: 35 | 36 | ```rust 37 | fn main() 38 | { 39 | let v = vec![20,30,40]; 40 | print!("element of a vector is :",v[5]); 41 | } 42 | ``` 43 | 44 | 执行上面范例程式码,得到以下结果 - 45 | 46 | ![img](https://tw511.com/upload/images/201910/20191014013938398.png) 47 | 48 | 49 | 50 | 在上面的例子中,试图存取索引 在这种情况下,Rust会因为存取无效索引而引发 因此,Rust不会返回任何内容。但是,对于其他语言(如C和C++),它们会返回一些内容,尽管该向量不属于该记忆体。这称为缓冲区重写,它会导致安全问题。`5` `panic` 51 | 52 | **Rust回溯 需要设定** 53 | `RUST_BACKTRACE` 54 | -------------------------------------------------------------------------------- /入门秘笈/Rust公开函式.md: -------------------------------------------------------------------------------- 1 | # Rust公开函式 2 | 3 | `pub`关键字用于宣告的开头,以便外部函式可以存取该函式。 4 | 5 | **以下是私有规则:** 6 | 7 | - 如果任何函式或模组是公共的,则任何父模组都可以存取它。 8 | - 如果任何函式或模组是私有的,则可以通过其直接父模组或父项的子模组来存取它。 9 | - 通过下面一个简单的例子来理解这一点: 10 | 11 | ```rust 12 | mod outer 13 | { 14 | pub fn a() 15 | { 16 | println!("function a"); 17 | } 18 | fn b() 19 | { 20 | println!("function b"); 21 | } 22 | 23 | mod inner 24 | { 25 | pub fn c() 26 | { 27 | println!("function c"); 28 | } 29 | fn d() 30 | { 31 | println!("function d"); 32 | } 33 | } 34 | } 35 | fn main() 36 | { 37 | outer::a(); 38 | outer::b(); 39 | outer::inner::c(); 40 | outer::inner::d(); 41 | } 42 | ``` 43 | 44 | 执行上面范例程式码,得到以下结果 - 45 | 46 | ![img](https://tw511.com/upload/images/201910/20191014013929389.png) 47 | 48 | 在上面的范例中,因此,`main()``outer``main()``outer` 49 | 50 | 函式`a()``outer::a()``main()``outer::b()` 51 | 52 | ``` 53 | main()`函式无法存取内部模组,因为它是私有的。模组没有子模组,因此只能由其父模组(即`inner``outer 54 | ``` 55 | -------------------------------------------------------------------------------- /入门秘笈/Rust切片.md: -------------------------------------------------------------------------------- 1 | # Rust切片 2 | 3 | 切片(Slice)是一种没有所有权的资料型别。切片参照连续的记忆体分配而不是整个集合。它允许安全,高效地存取阵列而无需复制。切片不是直接建立的,而是从现有变数建立的。切片由长度组成,并且可以是可变的或不可变的。切片的行为与阵列相同。 4 | 5 | ## 字串切片 6 | 7 | 字串切片指的是字串的一部分。切片看起来像: 8 | 9 | ```rust 10 | let str=String::from("Tw511.com tutorial"); 11 | let yiibai=&str[0..10]; 12 | let tutorial=&str[11,18]; 13 | ``` 14 | 15 | 如果想要取一部分字串,而不是整个字串。语法是一个从开始但不包括结束的范围。因此,可以通过指定括号内的范围来建立切片,例如 如果想要包含字串的结尾,那么必须使用`[start..end]``[start..end]``start``end``..=``..` 16 | 17 | ```rust 18 | let str= String::from("tw511.com tutorial"); 19 | let yiibai = &str[0..=9]; 20 | let tutorial= &str[11..=18] ; 21 | ``` 22 | 23 | 图解表示: 24 | 25 | ![img](https://tw511.com/upload/images/201910/20191014013916385.png) 26 | 27 | 如果要从 看起来如下:`0` 28 | 29 | ```rust 30 | let str= String::from("hello world"); 31 | let hello = &str[0..5]; 32 | let hello=&str[..5]; 33 | ``` 34 | 35 | 如果 看起来如下:`slice` 36 | 37 | ```rust 38 | let str= String::from("hello world") ; 39 | let hello=&str[6..len]; 40 | let world = &str[6..]; 41 | ``` 42 | 43 | 下面来看一个字串切片的简单范例: 44 | 45 | ```rust 46 | fn main(){ 47 | 48 | let str=String::from("Tw511.com tutorial"); 49 | let yiibai=&str[..=9]; 50 | println!("first word of the given string is {}",yiibai); 51 | } 52 | ``` 53 | 54 | 执行上面范例程式码,得到以下结果 - 55 | 56 | ```shell 57 | first word of the given string is Tw511.com 58 | ``` 59 | 60 | **字串切片是文字** 61 | 62 | 字串文字储存在二进位制档案中,字串文字仅作为字串切片。如下: 63 | 64 | ```rust 65 | let str = "Hello Yiibai" ; 66 | str`的型别是 字串文字是不可变的,`&str``&str 67 | ``` 68 | 69 | ## 字串切片作为引数 70 | 71 | 如果有一个字串切片,那么可以直接传递它作为引数。将字串切片作为引数传递给函式,而不是传递参照,以使API更通用和有用,而不会失去其功能。 72 | 73 | ```rust 74 | fn main() 75 | { 76 | let str= String:: from("Computer Science"); 77 | let first_word= first_word(&str[..]); //first_word function finds the first word of the string. 78 | let s="Computer Science" ; //string literal 79 | let first_word=first_word(&s[..]); // first_word function finds the first word of the string. 80 | let first_word=first_word(s) ; //string slice is same as string literal. Therefore, it can also be written in this way also. 81 | } 82 | ``` 83 | 84 | ## 其他切片 85 | 86 | 阵列也可以视为切片。它们的行为类似于字串切片。切片的型别为 它们通过将参照储存为第一个元素并将长度储存为第二个元素,类似于字串切片。`[&i32]` 87 | 88 | 考虑下面一个阵列: 89 | 90 | ```rust 91 | let arr = [100,200,300,400,500]; // array initialization 92 | let a = &arr[1..=3]; // retrieving second,third and fourth element 93 | ``` 94 | 95 | 下面来看一个简单的例子。 96 | 97 | ```rust 98 | fn main() 99 | 100 | let arr = [100,200,300,400,500,600]; 101 | let mut i=0; 102 | let a=&arr[1..=3]; 103 | let len=a.len(); 104 | println!("Elements of 'a' array:"); 105 | while iusize 23 | { 24 | s.len() 25 | } 26 | ``` 27 | 28 | 执行上面范例程式码,得到以下结果 - 29 | 30 | ``` 31 | length of the string 6 32 | ``` 33 | 34 | 在上面的范例中,`calculate_length()``str` 35 | 36 | ```rust 37 | let str=String::from("Yiibai"); 38 | let len=calculate_length(&str); 39 | ``` 40 | 41 | 在上面的场景中,因此,即使参照超出范围,也不会删除参照指向的值。`&str``str` 42 | 43 | ```rust 44 | fn calculate_length(s:&String)->usize 45 | s.len() 46 | ``` 47 | 48 | 在上面的例子中,变数 当变数作为函式的参照而不是实际值传递时,不需要返回值到返回所有权。`s``main()` 49 | 50 | 下面尝试修改借用的值。 51 | 52 | ```rust 53 | fn main() 54 | { 55 | let x=1; 56 | value_changed(&x) 57 | } 58 | fn value_changed(y:&i32) 59 | { 60 | *y=9; 61 | } 62 | ``` 63 | 64 | 以下是上述程式的输出: 65 | 66 | ![img](https://tw511.com/upload/images/201910/20191014013915384.png) 67 | 68 | 在上面的范例中,它会引发错误,因为 因此,无法改变`&x``y` 69 | 70 | ## 可变参照 71 | 72 | 可以通过使用可变参照来修复上述错误。可变参照是那些可以改变的参照。下面通过一个例子来理解这一点。 73 | 74 | ```rust 75 | fn main() 76 | { 77 | let mut x=1; 78 | value_changed(&mut x); 79 | println!("After modifying, the value of x is {}",x); 80 | } 81 | fn value_changed(y:&mut i32) 82 | { 83 | *y=9; 84 | } 85 | ``` 86 | 87 | 执行上面范例程式码,得到以下结果 - 88 | 89 | ```shell 90 | After modifying, the value of x is 9 91 | ``` 92 | 93 | 在上面的例子中,建立了一个可变参照,即 现在,可以更改 分配 因此,`&mut x``y``&i32``y``9``* y = 9``x``9` 94 | 95 | ## 可变参照的限制 96 | 97 | 只能对特定范围内的一段资料进行一次可变参照。例如: 98 | 99 | ```rust 100 | let mut str=String::from("Yiibai"); 101 | let a= &mut str; 102 | let b= &mut str; 103 | ``` 104 | 105 | 在上面的场景中,编译器丢掷一个错误,因为它包含两个在Rust语言中不可能的可变参照。如果程式中存在不可变参照,那么程式中就不能有可变参照。例如: 106 | 107 | ```rust 108 | let mut str=String::from("Yiibai"); 109 | let a= &str; 110 | let b=&str; 111 | let c=&mut str; 112 | ``` 113 | 114 | 在上面的场景中,编译器丢掷一个错误,因为当有一个不可变参照时,不能有一个可变参照。 115 | -------------------------------------------------------------------------------- /入门秘笈/Rust可恢复的错误.md: -------------------------------------------------------------------------------- 1 | # Rust可恢复的错误 2 | 3 | 可恢复的错误是那些完全停止程式并不严重的错误。可以处理的错误称为可恢复错误。它由 结果 4 | `Result ` `` `OK ` `Err ` 5 | 6 | ``` 7 | OK `:'T'是一种值,它在成功情况下时返回 :'E'是一种错误,它在失败情况下时返回`OK` 8 | `Err ``ERR 9 | Enum Result 10 | { 11 | OK, 12 | Err, 13 | } 14 | ``` 15 | 16 | - 在上面的例子中,`Result` `OK &Err ` `'T'` `'E'` 17 | - `'T'`是一种值,它将在成功的情况下返回,而`'E'` 18 | - `Result`包含泛型型别引数,因此在成功和失败值可能不同的许多不同情况下使用标准库中定义的结果型别和函式。 19 | 20 | 下面来看一个返回`Result` 21 | 22 | ```rust 23 | use std::fs::File; 24 | fn main() 25 | { 26 | let f:u32 = File::open("vector.txt"); 27 | } 28 | ``` 29 | 30 | 执行上面范例程式码,得到以下结果 - 31 | 32 | ![img](https://tw511.com/upload/images/201910/20191014013940399.png) 33 | 34 | 在上面的范例中,Rust编译器显示该型别不匹配。是 上面的输出显示成功值的型别是`'f'` `u32` `File::open` `Result ` `std::fs::File` `std::io::Error` 35 | 36 | **注意:** 37 | 38 | - `File::open`返回型别是成功值或失败值。如果 结果列举提供此资讯。`File::open` `File::open` 39 | - 如果`File::open` `f` `OK` `File::open` `Err` 40 | 41 | ## 匹配表示式以处理结果变体 42 | 43 | 下面来看看一个匹配表示式的简单范例: 44 | 45 | ```c 46 | use std::fs::File; 47 | fn main() 48 | { 49 | let f = File::open("vector.txt"); 50 | match f 51 | { 52 | Ok(file) => file, 53 | Err(error) => { 54 | panic!("There was a problem opening the file: {:?}", error) 55 | }, 56 | }; 57 | } 58 | ``` 59 | 60 | 执行上面范例程式码,得到以下结果 - 61 | 62 | ![img](https://tw511.com/upload/images/201910/20191014013940400.png) 63 | 64 | **程式说明** 65 | 66 | - 在上面的范例中,可以直接存取列举变体,而无需在`OK` `Err` `Result::` 67 | - 如果结果正常,则返回档案并将其储存在 在匹配之后,可以在档案中执行读取或写入操作。`'f'` 68 | - 匹配对 如果`Err` `Result` `Error` `panic!` 69 | 70 | #### 出错时Error:unwrap() 71 | 72 | - 结果 其中一种方法是 方法是匹配表示式的快捷方法。方法和匹配表示式的工作方式是一样的。```unwrap()``unwrap()``unwrap()` 73 | - 如果`Result` `OK` `unwrap()` `OK` 74 | - 如果`Result` `Err` `unwrap()` `panic!` 75 | 76 | 下面来看一个简单的范例: 77 | 78 | ```rust 79 | use std::fs::File; 80 | 81 | fn main() 82 | { 83 | File::open("hello.txt").unwrap(); 84 | } 85 | ``` 86 | 87 | 执行上面范例程式码,得到以下结果: 88 | 89 | ![img](https://tw511.com/upload/images/201910/20191014013940401.png) 90 | 91 | 在上面的例子中,`unwrap()` `panic!` 92 | 93 | #### Error: expect() 94 | 95 | - `expect()`方法的行为方式与`unwrap()` `panic!` 96 | - `expect()`和 因此,可以说`unwrap()` `expect()` `unwrap()` `expect()` `panic!` 97 | 98 | 下面看看一个简单范例 - 99 | 100 | ```shell 101 | use std::fs::File; 102 | fn main() 103 | { 104 | File::open("hello.txt").expect("Not able to find the file hello.txt"); 105 | } 106 | ``` 107 | 108 | 执行上面范例程式码,得到以下结果 - 109 | 110 | ![img](https://tw511.com/upload/images/201910/20191014013940402.png) 111 | 112 | 在上面的输出中,错误讯息显示在程式中指定的输出萤幕上,即 如果包含多个`「無法找到檔案hello.txt」` `unwrap()` `unwrap()` `panic!` 113 | 114 | ## 传播错误 115 | 116 | 传播错误是一种将错误从一个函式转发到另一个函式的机制。错误传播到呼叫函式,其中有更多资讯可用,以便可以处理错误。假设有一个名为 想要建立一个程式来读取档案,先参考下面一个简单的例子: 117 | 118 | ```rust 119 | use std::io; 120 | use std::io::Read; 121 | use std::fs::File; 122 | fn main() 123 | { 124 | let a = read_username_from_file(); 125 | print!("{:?}",a); 126 | } 127 | fn read_username_from_file() -> Result 128 | { 129 | let f = File::open("a.txt"); 130 | let mut f = match f { 131 | Ok(file) => file, 132 | Err(e) => return Err(e), 133 | }; 134 | let mut s = String::new(); 135 | match f.read_to_string(&mut s) { 136 | Ok(_) => Ok(s), 137 | Err(e) => Err(e), 138 | } 139 | } 140 | ``` 141 | 142 | 程式说明 - 143 | 144 | - `read_username_from_file()`函式返回`Result ` `'T'` `String` `'E'` `io` `Error` 145 | - 如果函式成功,则返回一个包含`String` `OK` `Err` 146 | - 函式中首先呼叫 如果`File::open` `File::open` `Err` `File::open``f` 147 | - 如果 如果`File::open` `String` `read_to_string()` 148 | - 假设我们有一个名为 因此,该程式读取档案 149 | 150 | #### 传播错误的捷径:`?` 151 | 152 | 使用 运算子是匹配表示式的替换意味着 假设有一个名为 想要建立一个程式来对该档案执行读取操作。`?` `?` `?` `「yiibai」` 153 | 154 | 看看下面一个简单的例子。 155 | 156 | ```c 157 | use std::io; 158 | use std::io::Read; 159 | use std::fs::File; 160 | fn main() 161 | { 162 | let a = read_username_from_file(); 163 | print!("{:?}",a); 164 | } 165 | fn read_username_from_file() -> Result 166 | { 167 | let mut f = File::open("a.txt")?; 168 | let mut s = String::new(); 169 | f.read_to_string(&mut s)?; 170 | Ok(s) 171 | } 172 | ``` 173 | 174 | 在上面的例子中,如果`?` `Result` `Result` `OK` `OK` `Result` `Err` 175 | 176 | #### ?运算子和匹配表示式的区别 177 | 178 | - 使用`?` `from trait` 179 | - 当`?` 180 | - 如果没有错误发生,那么`?` `OK` `Err` 181 | - 它使函式的实现更简单。 182 | 183 | #### 链方法在?运算子之后呼叫 184 | 185 | 甚至可以通过在`?` 186 | 187 | 下面来看一个简单的例子: 188 | 189 | ```rust 190 | use std::io; 191 | use std::io::Read; 192 | use std::fs::File; 193 | fn main() 194 | { 195 | let a = read_username_from_file(); 196 | print!("{:?}",a); 197 | } 198 | fn read_username_from_file() -> Result 199 | { 200 | let mut s = String::new(); 201 | File::open("a.txt")?.read_to_string(&mut s)?; 202 | Ok(s) 203 | } 204 | ``` 205 | 206 | **程式说明** 207 | 208 | 在上面的例子中,将 如果两个函式(即`read_to_string()` `File::open("a.txt")?` `read_to_string()` `File::open("a.txt")` `OK` 209 | 210 | #### ?运算子的限制 211 | 212 | `?`运算子只能在返回 运算子与匹配表示式的工作方式类似。匹配表示式仅适用于`Result` `?` `Result` 213 | 214 | 下面通过一个简单的例子来理解这一点。 215 | 216 | ```rust 217 | use std::fs::File; 218 | fn main() 219 | { 220 | let f = File::open("a.txt")?; 221 | } 222 | ``` 223 | -------------------------------------------------------------------------------- /入门秘笈/Rust向量.md: -------------------------------------------------------------------------------- 1 | # Rust向量 2 | 3 | 向量是一种单一资料结构,可以在记忆体中彼此相邻地储存多个值。当有一个专案列表(例如:购物车中的资料项)时,向量很有用。 4 | 5 | **要点:** 6 | 7 | - 向量用于储存相同型别的值。 8 | - 向量由`Vec ` 9 | - `Vec `由标准库提供,它可以储存任何型别的资料,其中`T` 10 | - 向量的资料在堆上分配。 11 | - 向量是一个可增长的阵列意味着可以在执行时新增新元素。 12 | 13 | `Vec ` :当向量保持特定型别时,它在角括号中表示。 14 | 15 | ## 如何建立向量? 16 | 17 | 可以使用`Vec::new()` 18 | 19 | ```rust 20 | Let v : Vec = Vec::new(); 21 | ``` 22 | 23 | 在上面的宣告中,`v``i32``Vec::new()` 24 | 25 | 还有另一种建立向量的方法: 26 | 27 | Rust提供`vec!` 28 | 29 | 例如: 30 | 31 | ```rust 32 | let v = vec![10,20,30,40,50]; 33 | ``` 34 | 35 | 注意:如果想重复向量的初始值,那么还有另一种实现`vec` 36 | 37 | ```rust 38 | let v = vec![2 ; i]; 39 | ``` 40 | 41 | 在上面的宣告中,向量`v``2``i` 42 | 43 | ## 存取元素 44 | 45 | 可以使用下标运算子`[]` 46 | 47 | 通过下面一个例子来理解: 48 | 49 | ```rust 50 | fn main() 51 | { 52 | let v =vec![20,30,40,50]; 53 | println!("first element of a vector is :{}",v[0]); 54 | println!("Second element of a vector is :{}",v[1]); 55 | println!("Third element of a vector is :{}",v[2]); 56 | println!("Fourth element of a vector is :{}",v[3]); 57 | } 58 | ``` 59 | 60 | 执行上面范例程式码,得到以下结果 - 61 | 62 | ```shell 63 | first element of a vector is :20 64 | Second element of a vector is :30 65 | Third element of a vector is :40 66 | Fourth element of a vector is :50 67 | ``` 68 | 69 | 存取向量元素的第二种方法是使用`get(index)``vector``Option <&t>` 70 | 71 | 看下面一个范例程式码 - 72 | 73 | ```rust 74 | fn value(n:Option<&i32>) 75 | { 76 | match n 77 | { 78 | Some(n)=>println!("Fourth element of a vector is {}",n), 79 | None=>println!("None"), 80 | } 81 | } 82 | fn main() 83 | { 84 | let v =vec![20,30,40,50]; 85 | let a: Option<&i32>=v.get(3); 86 | value(a); 87 | } 88 | ``` 89 | 90 | 执行上面范例程式码,得到以下结果 - 91 | 92 | ```shell 93 | Fourth element of a vector is 50 94 | ``` 95 | 96 | 在上面的范例中,`get()` 97 | 98 | ## []和get()方法的区别: 99 | 100 | 当使用 因此,当尝试存取不存在的元素时,程式就会崩溃。如果尝试使用`[]``get()``None` 101 | 102 | 通过下面一个例子来理解这一点: 103 | 104 | - get(index)函式 105 | 106 | ```rust 107 | fn value(n:Option<&i32>) 108 | { 109 | match n 110 | { 111 | Some(n)=>println!("Fourth element of a vector is {}",n), 112 | None=>println!("None"), 113 | } 114 | } 115 | fn main() 116 | { 117 | let v =vec![20,30,40,50]; 118 | let a: Option<&i32>=v.get(7); 119 | value(a); 120 | } 121 | ``` 122 | 123 | 执行上面范例程式码,得到以下结果 - 124 | 125 | ```shell 126 | None 127 | ``` 128 | 129 | - []运算子 130 | 131 | ```rust 132 | fn main() 133 | { 134 | let v =vec![20,30,40,50]; 135 | println!("{}",v[8]); 136 | } 137 | ``` 138 | 139 | 执行上面范例程式码,得到以下结果 - 140 | 141 | ![img](https://tw511.com/upload/images/201910/20191014013932390.png) 142 | 143 | ## 叠代向量中的值 144 | 145 | 如果想要存取向量的每个元素,那么可以叠代向量的元素,而不是使用索引来存取向量的特定元素。 146 | 147 | 可以使用`for` 148 | 149 | 下面来看一个不可变参照的简单范例: 150 | 151 | ```rust 152 | fn main() 153 | { 154 | let v =vec![20,30,40,50]; 155 | print!("Elements of vector are :"); 156 | for i in v 157 | { 158 | print!("{} ",i); 159 | } 160 | } 161 | ``` 162 | 163 | 执行上面范例程式码,得到以下结果 - 164 | 165 | ```shell 166 | Elements of vector are :20 30 40 50 167 | ``` 168 | 169 | 下面来看一个可变参照的简单范例: 170 | 171 | ```rust 172 | fn main() 173 | { 174 | let mut v =vec![20,30,40,50]; 175 | print!("Elements of vector are :"); 176 | for i in &mut v 177 | { 178 | *i+=20; 179 | print!("{} ",i); 180 | } 181 | } 182 | ``` 183 | 184 | 执行上面范例程式码,得到以下结果 - 185 | 186 | ```shell 187 | Elements of vector are :20 30 40 50 188 | ``` 189 | 190 | 在上面的例子中,改变向量的值。因此,向量是可变参考。在`i``*``v` 191 | 192 | ## 更新向量 193 | 194 | 当建立向量时,使用 在向量的末尾插入新元素。`push()``push()` 195 | 196 | 下面来看看一个简单的例子: 197 | 198 | ```rust 199 | fn main() 200 | { 201 | let mut v=Vec::new(); 202 | v.push('j'); 203 | v.push('a'); 204 | v.push('v'); 205 | v.push('a'); 206 | for i in v 207 | { 208 | print!("{}",i); 209 | } 210 | } 211 | ``` 212 | 213 | 执行上面范例程式码,得到以下结果 - 214 | 215 | ```shell 216 | java 217 | ``` 218 | 219 | 在上面的范例中,向量`push()``v` 220 | 221 | ## 删除向量 222 | 223 | 当向量超出范围时,它会自动删除或从记忆体中释放。通过一个简单的场景来理解这一点: 224 | 225 | ```rust 226 | fn main() 227 | { 228 | let v = !vec[30,40,50]; 229 | } # => v 在這裡被釋放,因為它超出了範圍。 230 | ``` 231 | 232 | 在上面的场景中,当向量超出范围时释放向量意味着将移除向量中存在的所有元素。 233 | 234 | ## 使用Enum储存多种型别 235 | 236 | 向量可以储存相同型别的元素,这是向量的一个很大的缺点。列举是一种自定义资料型别,它包含相同列举名称下的各种型别的变体。当想要将元素储存在不同型别的向量中时,使用列举型别。 237 | 238 | 下面通过一个例子来理解这一点: 239 | 240 | ```rust 241 | #[derive(Debug)] 242 | enum Values { 243 | A(i32), 244 | B(f64), 245 | C(String), 246 | } 247 | 248 | fn main() 249 | { 250 | let v = vec![Values::A(5), 251 | Values::B(10.7),Values::C(String::from("Yiibai"))]; 252 | for i in v 253 | { 254 | println!("{:?}",i); 255 | } 256 | } 257 | ``` 258 | 259 | 执行上面范例程式码,得到以下结果 - 260 | 261 | ```shell 262 | A(5) 263 | B(10.7) 264 | C(Yiibai) 265 | ``` 266 | 267 | **在向量中使用列举的优点:** 268 | 269 | - Rust在编译时知道向量元素的型别,以确定每个元素需要多少记忆体。 270 | - 当向量由一个或多个型别的元素组成时,对元素执行的操作将导致错误,但使用带有匹配的列举将确保可以在执行时处理每个可能的情况。 271 | -------------------------------------------------------------------------------- /入门秘笈/Rust字串.md: -------------------------------------------------------------------------------- 1 | # Rust字串 2 | 3 | Rust包含两种型别的字串:`&str` `String` 4 | 5 | **String** 6 | 7 | - 字串被编码为UTF-8序列。 8 | - 在堆记忆体上分配一个字串。 9 | - 字串的大小可以增长。 10 | - 它不是以空(`null` 11 | 12 | **&str** 13 | 14 | - `&str`也称为字串切片。 15 | - 它由`&[u8]` 16 | - `&str`用于检视字串中的资料。 17 | - 它的大小是固定的,即它不能调整大小。 18 | 19 | **String 和&str 的区别** 20 | 21 | - `String`是一个可变参照,而`&str` `String` `&str` 22 | - `String`包含其资料的所有权,而`&str` 23 | 24 | ## 建立一个新的字串 25 | 26 | 在建立向量时类似地建立`String` 27 | 28 | 建立一个空字串: 29 | 30 | ```rust 31 | Let mut s = String::new(); 32 | ``` 33 | 34 | 在上面的宣告中,现在,如果想在宣告时初始化String,可以通过使用`String` `new()` `to_string()` 35 | 36 | 在资料上实现`to_string()` 37 | 38 | ```rust 39 | let a = "Yiibai"; 40 | let s = a.to_string(); 41 | ``` 42 | 43 | 也可以直接在字串文字上实现`to_string` 44 | 45 | ```rust 46 | let s = "Yiibai".to_string(); 47 | ``` 48 | 49 | 下面通过一个例子来理解这一点: 50 | 51 | ```rust 52 | fn main() 53 | { 54 | let data="Yiibai"; 55 | let s=data.to_string(); 56 | print!("{} ",s); 57 | let str="tutorial".to_string(); 58 | print!("{}",str); 59 | } 60 | ``` 61 | 62 | 执行上面范例程式码,得到以下结果 - 63 | 64 | ```shell 65 | Yiibai tutorial 66 | ``` 67 | 68 | 建立 下面通过一个简单的例子来理解这一点:`String``String::from``String::new()` 69 | 70 | ```rust 71 | fn main() 72 | { 73 | let str = String::from("Yiibai tutorial"); 74 | print!("{}",str); 75 | } 76 | ``` 77 | 78 | 执行上面范例程式码,得到以下结果 - 79 | 80 | ```shell 81 | Yiibai tutorial 82 | ``` 83 | 84 | ## 更新字串 85 | 86 | 可以通过将更多资料推播到 也可以使用格式巨集的`String``String``String``+` 87 | 88 | ![img](https://tw511.com/upload/images/201910/20191014013934391.png) 89 | 90 | 使用 它将内容附加在字串的末尾。假设`push_str` `push` `push_str()` `push_str()` `s1` `s2` `s3` `s4` 91 | 92 | ```rust 93 | s1.push_str(s2); 94 | ``` 95 | 96 | 通过一个简单的例子来理解这一点: 97 | 98 | ```rust 99 | fn main() 100 | { 101 | let mut s=String::from("java is a"); 102 | s.push_str(" programming language"); 103 | print!("{}",s); 104 | } 105 | ``` 106 | 107 | 执行上面范例程式码,得到以下结果 - 108 | 109 | ```shell 110 | java is a programming language 111 | ``` 112 | 113 | `push_str()`函式不接受引数的所有权。下面通过一个简单的例子来理解。 114 | 115 | ```rust 116 | fn main() 117 | { 118 | let mut s1 = String::from("Hello"); 119 | let s2 = "World"; 120 | s1.push_str(s2); 121 | print!("{}",s2); 122 | } 123 | ``` 124 | 125 | 执行上面范例程式码,得到以下结果 - 126 | 127 | ```shell 128 | World 129 | ``` 130 | 131 | 如果`push_str()` `s2` 132 | 133 | `push()`:假设字串是`push()` `s1 ` `ch` `s1` 134 | 135 | ``` 136 | s1.push(ch); 137 | ``` 138 | 139 | 下面来看一个简单的范例 140 | 141 | ```rust 142 | fn main() 143 | { 144 | let mut s = String::from("java"); 145 | s.push('c'); 146 | print!("{}",s); 147 | } 148 | ``` 149 | 150 | 执行上面范例程式码,得到以下结果- 151 | 152 | ```shell 153 | javac 154 | ``` 155 | 156 | - 使用 下面来看一个范例程式码:`+` `+` `+` 157 | 158 | ```rust 159 | let s1 = String::from("Yiibai "); 160 | let s2 = String::from("tutorial!!"); 161 | let s3 = s1+&s2; 162 | ``` 163 | 164 | 再来看看一个简单的程式码: 165 | 166 | ```rust 167 | fn main() 168 | { 169 | let s1 = String::from("Yiibai"); 170 | let s2 = String::from(" tutorial!!"); 171 | let s3 = s1+&s2; 172 | print!("{}",s3); 173 | } 174 | ``` 175 | 176 | 执行上面范例程式码,得到以下结果 - 177 | 178 | ```shell 179 | Yiibai tutorial!! 180 | ``` 181 | 182 | 在上面的例子中,不再有效,使用 运算子呼叫`s3` `"Yiibai tutorial!!"` `s1` `s2` `&s2` `+` `+` `add()` 183 | 184 | ```rust 185 | fn add(self,s:&str)->String 186 | { 187 | } 188 | ``` 189 | 190 | 首先,根据 但是根据 但是,仍然可以在 因此,当呼叫`s2` `&` `s1` `add()` `&str` `String` `add()` `s2` `&String` `&str` `add` `s2` `&string` `&str` `add()` 191 | 192 | 其次,这意味着在语句`add()` `self` `add()` `self` `let s3 = s1 +&s2` `s1` 193 | 194 | 下面通过一个简单的例子来理解这一点: 195 | 196 | ```rust 197 | fn main() 198 | { 199 | let s1 = String::from("C"); 200 | let s2 = String::from("is"); 201 | let s3 = String::from("a"); 202 | let s4 = String::from("programming"); 203 | let s5 = String::from("language."); 204 | let s = format!("{} {} {} {} {}",s1,s2,s3,s4,s5); 205 | print!("{}",s); 206 | } 207 | ``` 208 | 209 | 执行上面范例程式码,得到以下结果: 210 | 211 | ```shell 212 | C is a programming language. 213 | ``` 214 | 215 | ## 字串中的索引 216 | 217 | `String`以 因此,字串无法编入索引。下面通过一个例子来理解这个概念:`UTF-8` 218 | 219 | ``` 220 | fn main() 221 | { 222 | let s = String::from("Yiibai"); 223 | print!("{}",s[1]); 224 | } 225 | ``` 226 | 227 | 执行上面范例程式码,得到类似以下的结果 - 228 | 229 | ```shell 230 | error[E0277]: the trait bound `std::string::String: std::ops::Index<{integer}>` is not satisfied 231 | --> jdoodle.rs:4:17 232 | | 233 | 4 | print!("{}",s[1]); 234 | | ^^^^ the type `std::string::String` cannot be indexed by `{integer}` 235 | | 236 | = help: the trait `std::ops::Index<{integer}>` is not implemented for `std::string::String` 237 | 238 | error: aborting due to previous error 239 | ``` 240 | 241 | 通过索引存取非常快。但是,字串以`UTF-8``n` 242 | 243 | ## 字串切片 244 | 245 | 字串中未提供索引,因为不知道索引操作的返回型别应具有位元组值,字元或字串切片。Rust提供了一种更具体的方法来索引字串,方法是在`[]` 246 | 247 | **范例:** 248 | 249 | ```rust 250 | let s = "Hello World"; 251 | let a = &s[1..4]; 252 | ``` 253 | 254 | 在上面的场景中,这里指定`s` `"Hello World"` `[1..4]` `1` `3` 255 | 256 | ```rust 257 | fn main() { 258 | 259 | let s = "Hello World"; 260 | let a = &s[1..4]; 261 | print!("{}",a); 262 | } 263 | ``` 264 | 265 | 执行上面范例程式码,得到以下结果 - 266 | 267 | ```shell 268 | ell 269 | ``` 270 | 271 | ## 叠代字串的方法 272 | 273 | 也可以通过其他方式存取字串。使用`chars()` 274 | 275 | 下面来看一个简单的例子: 276 | 277 | ``` 278 | fn main() 279 | { 280 | let s = "C is a programming language"; 281 | for i in s.chars() 282 | { 283 | print!("{}",i); 284 | } 285 | } 286 | ``` 287 | 288 | 执行上面范例程式码,得到以下结果 - 289 | 290 | ``` 291 | C is a programming language 292 | ``` 293 | -------------------------------------------------------------------------------- /入门秘笈/Rust开发环境安装.md: -------------------------------------------------------------------------------- 1 | # Rust开发环境安装 2 | 3 | 在学习Rust之前。首先,需要安装Rust,通过 `rustup` 4 | 5 | ## Windows上Rust安装 6 | 7 | 在Windows上,开启连结 按照所有说明操作后,将安装Rust并显示萤幕:`rustup-init.exe` 8 | 9 | ![img](https://tw511.com/upload/images/201910/20191014013900370.png) 10 | 11 | 12 | 13 | 接着回车 - 14 | 15 | ![img](https://tw511.com/upload/images/201910/20191014013900371.png) 16 | 17 | 18 | 19 | 然后开始下载并安装Rust 环境。 20 | 21 | 安装后,Rust的PATH变数会自动新增到系统PATH中。开启命令提示字元然后执行以下命令: 22 | 23 | ```shell 24 | $ rustc --version 25 | ``` 26 | 27 | 执行此命令后,应该看到版本号,提交的杂凑值和提交日期。如果看到类似的结果,则表示Rust已成功安装。 28 | 29 | 结果如下所示 - 30 | 31 | ``` 32 | C:\Users\hema>rustc --version 33 | rustc 1.30.0 (da5f414c2 2018-10-24) 34 | ``` 35 | 36 | > 注意:使用C++工具安装visual studio是执行rust程式的必要条件。 37 | 38 | ## Linux或macOS中的Rust安装 39 | 40 | 如果使用的是Linux或macOS,请开启终端然后使用以下命令: 41 | 42 | ```shell 43 | $ curl https://sh.rustup.rs -sSf | sh 44 | ``` 45 | 46 | 上面的命令下载指令码并开始安装Rust工具,它将安装最新版本的Rust。如果安装成功完成,则会显示以下讯息: 47 | 48 | ```shell 49 | Rust is installed now. Great! 50 | ``` 51 | 52 | 下次登入后,此安装会自动将Rust新增到系统路径中。如果要立即执行Rust而不重新启动终端,请执行以下命令到`shell` 53 | 54 | ```shell 55 | $ source $HOME/.cargo/env 56 | ``` 57 | 58 | 安装后,需要一个连结器。当尝试执行Rust程式时,将收到连结器无法执行的错误。这意味着系统中未安装连结器。C编译器总是提出正确的编译器。安装C编译器。另外,一些Rust包依赖于C程式码,需要一个C编译器。 59 | 60 | ## 更新和解除安装 61 | 62 | **更新:执行以下命令以更新到最新版本:** 63 | 64 | ```shell 65 | $ rustup update 66 | ``` 67 | 68 | **解除安装:** 69 | 70 | ```shell 71 | $ rustup self uninstall 72 | ``` 73 | -------------------------------------------------------------------------------- /入门秘笈/Rust所有权.md: -------------------------------------------------------------------------------- 1 | # Rust所有权 2 | 3 | 所有权是Rust程式设计语言提供的独特功能,可在不使用垃圾收集器或指标的情况下提供记忆体安全保障。 4 | 5 | ## 什么是所有权? 6 | 7 | 当程式码块拥有资源时,它被称为所有权。程式码块建立一个包含资源的物件。当控制元件到达块的末尾时,物件将被销毁,资源将被释放。 8 | 9 | **所有权的重点:** 10 | 11 | - 「所有者」可以根据可变性改变变数的拥有值。 12 | - 所有权可以转移到另一个变数。 13 | - 所有权只是在Rust中移动语意。 14 | - 所有权模型也保证了并行的安全性。 15 | 16 | **所有权规则** 17 | 18 | - 在Rust中,每个值都有一个与之关联的变数,并称为其所有者。 19 | - 一次只能有一个所有者。 20 | - 当所有者超出范围时,与其关联的值将被销毁。 21 | 22 | **所有权的例子** 23 | 24 | 多个变数可以在Rust中相互互动。下面来看一个例子: 25 | 26 | 将`x``y` 27 | 28 | ```rust 29 | let x=10; 30 | let y=x; 31 | ``` 32 | 33 | 在上面的例子中,然后,在这种情况下,不会建立 因此,如果尝试重用变数 可通过下面的例子来理解这一点。`x``10``x``y``x``x``y``x``y``x``x` 34 | 35 | ```rust 36 | fn main() 37 | { 38 | let x=10; 39 | let y=x; 40 | println!("value of x :{}",x); 41 | } 42 | ``` 43 | 44 | 编译上面程式码,范例的输出如下: 45 | 46 | ![img](https://tw511.com/upload/images/201910/20191014013912378.png) 47 | 48 | ## 记忆体和分配 49 | 50 | 在Rust中,资料可以储存在堆叠或堆记忆体中。 51 | 52 | ![img](https://tw511.com/upload/images/201910/20191014013912379.png) 53 | 54 | **堆叠储存器:它遵循「后进先出」的原则,即始终首先删除最后插入的资料。堆叠记忆体是一种有组织的记忆体。它比堆记忆体更快,因为它存取记忆体的方式。如果在编译时资料的大小未知,则堆记忆体用于储存内容。** 55 | 56 | **堆记忆体:作业系统在堆记忆体中找到一个空的空格并返回一个指标。此过程称为「在堆上分配」。** 57 | 58 | ![img](https://tw511.com/upload/images/201910/20191014013912380.png) 59 | 60 | 此图显示堆叠包含指标,而堆包含内容。 61 | 62 | 下面来看一个简单的记忆体分配范例。 63 | 64 | ```rust 65 | fn main() 66 | { 67 | let v1=vec![1,2,3]; 68 | let v2=v1; 69 | } 70 | ``` 71 | 72 | **第1步:向量由三部分组成,即指向储存器中指向储存在记忆体中的资料的指标,长度和向量的容量。这些部分储存在堆叠中,而资料储存在堆记忆体中,如下所示:** 73 | `v1``1``2``3` 74 | 75 | ![img](https://tw511.com/upload/images/201910/20191014013912381.png) 76 | 77 | **第2步:指标,长度和容量将复制到堆叠中,但不会将资料复制到堆记忆体中。现在记忆体的表示如下:** 78 | `v1``v2` 79 | 80 | ![img](https://tw511.com/upload/images/201910/20191014013912382.png) 81 | 82 | 但是,这种表示形式可能会产生问题。当 这会导致双重空闲记忆体,这会导致记忆体损坏。`v1``v2` 83 | 84 | **第3步:Rust没有复制分配的记忆体,而是认为 因此,当** 85 | `v1``v1``v1` 86 | 87 | ![img](https://tw511.com/upload/images/201910/20191014013912383.png) 88 | 89 | ## 使用复制特征 90 | 91 | 复制特征是一种特殊的注释,它放在储存在堆叠上的整数型别上。如果在型别上使用了复制特征,则即使在赋值操作之后也可以进一步使用旧变数。 92 | 93 | 以下是一些复制型别: 94 | 95 | - 所有整数型别,如`u32` 96 | - 布林型别-`bool``true``false` 97 | - 所有浮动型别,如`f64` 98 | - 字元型别,如`char` 99 | 100 | ## 所有权和函式 101 | 102 | 当变数传递给函式时,所有权将移动到被呼叫函式的变数。传递值的语意等于为变数赋值。 103 | 104 | 下面通过一个例子来理解这一点: 105 | 106 | ```rust 107 | fn main() 108 | { 109 | let s=String::from("Yiibai"); 110 | take_ownership(s); 111 | let ch='a'; 112 | moves_copy(ch); 113 | println!("{}",ch); 114 | } 115 | fn take_ownership(str:String) 116 | { 117 | println!("{}",str); 118 | } 119 | fn moves_copy(c:char) 120 | { 121 | println!("{}",c); 122 | } 123 | ``` 124 | 125 | 执行上面范例程式码,得到以下结果 - 126 | 127 | ``` 128 | Yiibai 129 | a 130 | a 131 | ``` 132 | 133 | 在上面的例子中,字串 变数与值 之后也可以使用`s``Yiibai``s``take_ownership()``str``ch``a``ch``moves_copy()``c``ch` 134 | 135 | ## 返回值和范围 136 | 137 | 从函式返回值也会转移所有权。看看这个范例: 138 | 139 | ```rust 140 | fn main() 141 | { 142 | let x= gives_ownership(); 143 | println!("value of x is {}",x); 144 | } 145 | fn gives_ownership()->u32 146 | { 147 | let y=100; 148 | y 149 | } 150 | ``` 151 | 152 | 执行上面范例程式码,得到以下结果 - 153 | 154 | ``` 155 | value of x is 100 156 | ``` 157 | 158 | 在上面的例子中,`give_ownership()``y``100``y``x` 159 | -------------------------------------------------------------------------------- /入门秘笈/Rust智慧指标.md: -------------------------------------------------------------------------------- 1 | # Rust智慧指标 2 | 3 | 智慧指标是一种资料结构,其行为类似于指标,同时提供记忆体管理或系结检查等附加功能。智慧指标可跟踪其指向的记忆体,还可用于管理其他资源,如 智慧指标最初用于C++语言。参照也是一种指标,但除了参照资料之外,它没有其他功能。参照由 智慧指标提供的功能超出了参考提供的功能。智慧指标提供的最常见功能是「参照计数智慧指标型别」。此功能能够通过跟踪所有者来拥有多个资料所有者,如果没有所有者,则可以清除资料。参照是仅借用资料的指标,而智慧指标是拥有它们指向的资料的指标。 4 | `Fils` 5 | 6 | ``` 7 | & 8 | ``` 9 | 10 | **智慧指标的型别:** 11 | 12 | ![img](https://tw511.com/upload/images/201910/20191014013949409.png) 13 | 14 | - `Box `:它用于将资料储存在堆上而不是堆叠上。`Box ` 15 | - `Deref `:`Deref ` `*` 16 | - `Drop `:`Drop ` 17 | - `Rc `:它是一个智慧指标,用于记录储存在堆上的值的参照数。`Rc ` 18 | - `RefCell `:这个过程被称为内部可变性。`RefCell ` 19 | -------------------------------------------------------------------------------- /入门秘笈/Rust档案系统.md: -------------------------------------------------------------------------------- 1 | # Rust档案系统 2 | 3 | ------ 4 | 5 | 模组形成层次结构,使专案变得更容易理解。Rust模组系统用于分割多个档案,使得并非所有内容都位于`src/lib.rs` `src/main.rs` 6 | 7 | 档案名: 8 | 9 | ```rust 10 | mod A 11 | { 12 | fn a() 13 | { 14 | // block of statements. 15 | } 16 | } 17 | mod B 18 | { 19 | fn b() 20 | { 21 | // block of statements. 22 | } 23 | mod C 24 | { 25 | fn c() 26 | { 27 | // block of statements. 28 | } 29 | } 30 | } 31 | ``` 32 | 33 | 在上面的例子中,程式由三个模组组成,即 是`A``B``C``C``B` 34 | 35 | 给定档案的模组层次结构是: 36 | 37 | ![img](https://tw511.com/upload/images/201910/20191014013928388.png) 38 | 39 | 如果模组包含许多函式并且函式非常冗长,则很难找到特定函式的程式码。Rust通过提供模组系统提供了灵活性。可以拥有每个模组的单独档案,而不是放在同一个档案中,即`src/lib.rs` 40 | 41 | **要遵循的步骤:** 42 | `A` 43 | 44 | ```rust 45 | mod A; 46 | mod B 47 | { 48 | fn b() 49 | { 50 | // block of statements. 51 | } 52 | mod C 53 | { 54 | fn c() 55 | { 56 | // block of statements. 57 | } 58 | } 59 | } 60 | ``` 61 | 62 | 分号`;``A``A` 63 | 64 | **模组A;** 65 | 66 | ```rust 67 | mod A 68 | { 69 | fn a() 70 | { 71 | // block of statements. 72 | } 73 | } 74 | ``` 75 | 76 | 现在建立包含模组A定义的外部档案。外部档案的名称将命名为- 建立档案后,在此档案中写入模组A的定义,该档案先前已被删除。 77 | 78 | 档案名: 79 | 80 | ```rust 81 | fn a() 82 | // block of statements. 83 | ``` 84 | 85 | 在这种情况下,不需要像在 并且,如果在这里编写`mod` `mod` `A` 86 | 87 | Rust预设情况下会检视`src/lib.rs` 88 | 89 | 现在,从档案`src/lib.rs` `B` `B` 90 | 91 | 档案名: 92 | 93 | ```rust 94 | mod A; 95 | mod B; 96 | ``` 97 | 98 | **mod B;** 99 | 100 | ```rust 101 | mod B 102 | 103 | fn b() 104 | { 105 | // block of statements. 106 | } 107 | mod C 108 | { 109 | fn c() 110 | { 111 | // block of statements. 112 | } 113 | } 114 | ``` 115 | 116 | 现在建立包含模组 外部档案的名称将命名为- 建立档案后,在此档案中写入先前已删除的模组`B` `src/B.rs` `B` 117 | 118 | 档案名:`src/B.rs` 119 | 120 | ```rust 121 | fn b() 122 | { 123 | // block of statements. 124 | } 125 | mod C 126 | { 127 | fn c() 128 | { 129 | // block of statements. 130 | } 131 | } 132 | ``` 133 | 134 | 现在将从档案`src/B.rs` `C` `C` 135 | 136 | ```rust 137 | fn b() 138 | { 139 | // block of statements. 140 | } 141 | mod C; 142 | ``` 143 | 144 | **mod C;** 145 | 146 | ```rust 147 | mod C 148 | { 149 | fn c() 150 | { 151 | // block of statements. 152 | } 153 | } 154 | ``` 155 | 156 | 现在建立包含模组 外部档案的名称将命名为 建立档案后,在此档案中写入模组`C``src/C.rs``C` 157 | 158 | 档案名称: 159 | 160 | ```rust 161 | fn c() 162 | { 163 | // block of statements. 164 | } 165 | ``` 166 | 167 | > 注意:从模组B中提取模组C将导致编译错误,因为 因此,`src/B.rs` `src/lib.rs` `src/B.rs` `src/B/mod.rs` `B` 168 | 169 | **模组档案系统规则:** 170 | 171 | - 如果模组名为「server」且没有子模组,则模组的所有宣告都可以放在档案`server.rs` 172 | - 如果名为「server」的模组包含子模组,则模组的所有宣告都将放在档案`server/mod.rs` 173 | -------------------------------------------------------------------------------- /入门秘笈/Rust模组.md: -------------------------------------------------------------------------------- 1 | # Rust模组 2 | 3 | 模组是一个名称空间,包含函式或其型别的定义。模组是函式,结构,特征,预设情况下,模组的修饰符是私有的,但可以使用`impl``pub``public` 4 | 5 | 以下是模组中使用的关键字: 6 | 7 | - **mod关键字**`mod` 8 | - **pub关键字 关键字使可见性修饰符成为公共,因此,它们可在名称空间外部存取。**`pub` 9 | - **use关键字**`use` 10 | 11 | ## 模组定义 12 | 13 | 模组由`mod` 14 | 15 | 模组的语法: 16 | 17 | ```rust 18 | mod module_name 19 | // body inside the module. 20 | ``` 21 | 22 | 模组可以通过三种方式分类: 23 | 24 | **1.单个模组:** 25 | 26 | 通过下面一个例子来理解这一点: 27 | 28 | ```rust 29 | mod a 30 | { 31 | pub fn single_module() 32 | { 33 | println!("Single module"); 34 | } 35 | } 36 | fn main() 37 | { 38 | a::single_module(); 39 | } 40 | ``` 41 | 42 | 执行上面范例程式码,得到以下结果 - 43 | 44 | ```shell 45 | Single module 46 | ``` 47 | 48 | 在上面的范例中,定义了一个模组- 可以使用模组名称后跟名称空间然后使用函式名称来呼叫模组`a``a``a` 49 | 50 | 也可以使用单独的档案来执行上面的范例: 51 | 52 | ```rust 53 | mod module; 54 | fn main() 55 | { 56 | module::single_module(); 57 | } 58 | pub fn single_module() 59 | { 60 | println!("Single module"); 61 | } 62 | ``` 63 | 64 | 执行上面范例程式码,得到以下结果 - 65 | 66 | ```shell 67 | Single module 68 | ``` 69 | 70 | 在上面两个例子中,检查`mod X``X.rs``X/mod.rs` 71 | 72 | **2.子模组:假设库名称是-**`language``C``Cplus` 73 | 74 | 下面给出了`language` 75 | 76 | ![img](https://tw511.com/upload/images/201910/20191014013926387.png) 77 | 78 | 通过下面一个例子来理解: 79 | 80 | ```rust 81 | mod c 82 | { 83 | pub fn c() 84 | { 85 | println!("C is a structured programming language"); 86 | } 87 | } 88 | mod cplus 89 | { 90 | pub fn cplus() 91 | { 92 | println!("C++ is an object-oriented programming language"); 93 | } 94 | } 95 | fn main() 96 | { 97 | c::c(); 98 | cplus::cplus(); 99 | } 100 | ``` 101 | 102 | 执行上面范例程式码,得到以下结果: 103 | 104 | ```shell 105 | C is a structured programming language 106 | C++ is an object-oriented programming language 107 | ``` 108 | 109 | 在上面的例子中,程式由两个模组组成,即`c``cplus``c::c()``cplus::cplus()` 110 | 111 | **3.巢状模组:** 112 | 113 | 通过下面一个例子来理解这一点: 114 | 115 | ```rust 116 | mod a 117 | { 118 | pub fn a() 119 | { 120 | println!("a module"); 121 | } 122 | pub mod b 123 | { 124 | pub fn a() 125 | { 126 | println!("b module"); 127 | } 128 | } 129 | } 130 | fn main() 131 | { 132 | a::a(); 133 | a::b::b(); 134 | } 135 | ``` 136 | 137 | 执行上面范例程式码,得到以下结果 - 138 | 139 | ```shell 140 | a module 141 | b module 142 | ``` 143 | 144 | 在上面的例子中,程式由两个模组组成,即 这两个模组都包含具有相同名称但功能不同。这两个函式分别使用 它们都不会相互冲突,因为它们属于不同的名称空间。`a``b``b``a``a::a()``a::b::b()` 145 | -------------------------------------------------------------------------------- /入门秘笈/Rust泛型.md: -------------------------------------------------------------------------------- 1 | # Rust泛型 2 | 3 | 当要建立多种形式的功能时,即,函式的引数可以接受多种型别的资料。这可以通过泛型来实现。泛型也称为「引数多型」,其中多型是多重的,而变形是形式。 4 | 5 | 有两种方法可以提供通用程式码: 6 | 7 | - `Option` 8 | - `Result` 9 | 10 | ![img](https://tw511.com/upload/images/201910/20191014013943403.png) 11 | 12 | 1. 它提供了一种型别的泛型。`Option` `Option` `'T'` 13 | 14 | ```rust 15 | enum Option 16 | { 17 | Some(T), 18 | None, 19 | } 20 | ``` 21 | 22 | 在上面的例子中,可以用任何资料型别替换 下面来看看这几个范例:`enum` `` `T` 23 | 24 | ```rust 25 | let x : Option = Some(10); // 'T' is of type i32. 26 | let x : Option = Some(true); // 'T' is of type bool. 27 | let x : Option = Some(10.5); // 'T' is of type f64. 28 | let x : Option = Some('b'); // 'T' is of type char. 29 | ``` 30 | 31 | 在上面的例子中,观察到 但是,如果左侧的型别与右侧的值不匹配,则会发生错误。如下范例:`'T'` `i32` `bool` `f64` `char` 32 | 33 | ```rust 34 | let x : Option = Some(10.8); 35 | ``` 36 | 37 | 在上述情况下,左侧的型别是 因此,错误发生「型别不匹配」。`i32` `f64` 38 | 39 | 1. `Result `: Rust标准库提供了另一种资料型别`Result ` `T&E` 40 | 41 | ```rust 42 | enum Result 43 | { 44 | OK(T), 45 | Err(E), 46 | } 47 | ``` 48 | 49 | > 注意:不得不使用`'T'` `'E'` 50 | 51 | #### 泛型函式 52 | 53 | 泛型可以在函式中使用,将泛型放在函式的签名中,其中指定引数的资料型别和返回值。 54 | 55 | - 当函式包含型别为`T` 56 | 57 | **语法** 58 | 59 | ```rust 60 | fn function_name(x:T) 61 | // body of the function. 62 | ``` 63 | 64 | 上面的语法包含两部分: 65 | 66 | - `` : 给定的函式是一种型别的泛型。 67 | - `(x : T)`: x 是型别`T` 68 | 69 | 当函式包含多个相同型别的引数时。 70 | 71 | ```rust 72 | fn function_name(x:T, y:T) 73 | // body of the function. 74 | ``` 75 | 76 | 当函式包含多个型别的引数时。 77 | 78 | ```rust 79 | fn function_name(x:T, y:U) 80 | // Body of the function. 81 | ``` 82 | 83 | 完整程式码 - 84 | 85 | ```rust 86 | fn main() 87 | { 88 | let a = vec![1,2,3,4,5]; 89 | let b = vec![2.3,3.3,4.3,5.3]; 90 | let result = add(&a); 91 | let result1 = add(&b); 92 | println!("The value of result is {}",result); 93 | println!("The value of result1 is {}",result1); 94 | } 95 | 96 | fn add(list:&[T])->T 97 | { 98 | let mut c =0; 99 | for &item in list.iter() 100 | { 101 | c= c+item; 102 | } 103 | } 104 | ``` 105 | 106 | ## 结构定义 107 | 108 | 结构也可以使用`<>` 109 | 110 | **语法:** 111 | 112 | ```rust 113 | struct structure_name 114 | // Body of the structure. 115 | ``` 116 | 117 | 在上面的语法中,在`struct_name` `struct` 118 | 119 | 下面我们来看一个简单的例子: 120 | 121 | ```rust 122 | struct Value 123 | { 124 | a:T, 125 | b:T, 126 | } 127 | fn main() 128 | { 129 | let integer = Value{a:2,b:3}; 130 | let float = Value{a:7.8,b:12.3}; 131 | println!("integer values : {},{}",integer.a,integer.b); 132 | println!("Float values :{},{}",float.a,float.b); 133 | } 134 | ``` 135 | 136 | 执行上面范例程式码,得到以下结果 - 137 | 138 | ```shell 139 | integer values : 2,3 140 | Float values : 7.8,12.3 141 | ``` 142 | 143 | 在上面的范例中,建立两个范例 包含`Value ` `a` `b` `integer` `float` `Integer` `i32` `float` `f64` 144 | 145 | 下面来看另一个简单的例子。 146 | 147 | ```rust 148 | struct Value 149 | { 150 | a:T, 151 | b:T, 152 | } 153 | fn main() 154 | { 155 | let c = Value{a:2,b:3.6}; 156 | println!("c values : {},{}",c.a,c.b); 157 | } 158 | ``` 159 | 160 | 执行上面范例程式码,得到以下结果: 161 | 162 | 163 | 164 | ![img](https://tw511.com/upload/images/201910/20191014013943404.png) 165 | 166 | 在上面的范例中,建立了一个 包含不同型别的值,即 因此,Rust编译器会丢掷「不匹配的错误」。`Value ` `a` `b` `c` `c` `i32` `f64` 167 | 168 | ## 列举定义 169 | 170 | 列举也可以使用通用资料型别。Rust标准库提供了 是一个列举,其中`Option ` `Option ` `T` 171 | 172 | - `Option` 173 | 174 | 它由两个变体组成,即`Some(T)` `None` 175 | 176 | ![img](https://tw511.com/upload/images/201910/20191014013943405.png) 177 | 178 | 其中`Some(T)` `T` `None` 179 | 180 | 看看下面一段范例程式码: 181 | 182 | ```rust 183 | enum Option 184 | { 185 | Some(T), 186 | None, 187 | } 188 | ``` 189 | 190 | 在上面的例子中,它由两个变体`Option` `T` `Some(T)` `None` 191 | 192 | ``` 193 | Result`:可以建立多种型别的泛型,这可以通过`Result 194 | enum Result 195 | { 196 | OK(T), 197 | Err(E), 198 | } 199 | ``` 200 | 201 | 在上面的例子中,`Result ` `OK(T)` `Err(E)` 202 | 203 | `OK(T)`保持型别`T` `Err(E)` `E` 204 | 205 | ## 方法定义 206 | 207 | 可以在结构和列举上实现这些方法。下来看看一个简单的例子: 208 | 209 | ```rust 210 | struct Program { 211 | a: T, 212 | b: T, 213 | } 214 | impl Program 215 | { 216 | fn a(&self) -> &T 217 | { 218 | &self.a 219 | } 220 | } 221 | 222 | fn main() { 223 | let p = Program{ a: 5, b: 10 }; 224 | 225 | println!("p.a() is {}", p.a()); 226 | } 227 | ``` 228 | 229 | 输出结果如下 - 230 | 231 | ```shell 232 | p.a() is 5 233 | ``` 234 | 235 | 在上面的例子中,在 在`Program ` `a` `a` `impl` `T` `Program ` 236 | 237 | ## 解决歧义 238 | 239 | Rust编译器自动推断通用引数。下面通过一个简单的场景来理解: 240 | 241 | ```rust 242 | Let mut v = Vec::new(); // creating a vector. 243 | v.push(10); // inserts integer value into the vector. Therefore, v is of i32 type. 244 | println!("{:?}", v); // prints the value of v. 245 | ``` 246 | 247 | 在上面的例子中,将整数值插入向量中。因此,Rust编译器知道向量`v``i32` 248 | 249 | 如果删除第二行,现在程式码如下所示 - 250 | 251 | ```rust 252 | Let mut v = Vec::new(); // creating a vector. 253 | println!("{:?}", v); // prints the value of v. 254 | ``` 255 | 256 | 上面的情况将丢掷「它无法推断出T的型别」的错误。 257 | 258 | 可以通过两种方式解决上述问题: 259 | 260 | 1. 使用以下注释: 261 | 262 | ```rust 263 | let v : Vec = Vec::new(); 264 | println!("{:?}",v) ; 265 | ``` 266 | 267 | 2. 使用`'turbofish':: <>``'T'` 268 | 269 | ```rust 270 | let v = Vec :: :: new(); 271 | println!("{:?}",v) ; 272 | ``` 273 | -------------------------------------------------------------------------------- /入门秘笈/Rust生命周期.md: -------------------------------------------------------------------------------- 1 | # Rust生命周期 2 | 3 | 生命周期定义了参照有效的范围。生命周期是隐含的和推断的。Rust使用通用生命周期引数来确保使用有效的实际参照。 4 | 5 | ## 预防与生命周期的悬空参照 6 | 7 | 当程式试图存取无效参照时称为悬空参照,所指向无效资源的指标称为悬空指标。 8 | 9 | 看看一个简单的例子: 10 | 11 | ```rust 12 | fn main() 13 | { 14 | let a; 15 | { 16 | let b = 10; 17 | a = &b; 18 | } 19 | println!("a : {}",a); 20 | } 21 | ``` 22 | 23 | 输出结果如下 - 24 | 25 | ![img](https://tw511.com/upload/images/201910/20191014013947406.png) 26 | 27 | 在上面的范例中,外部作用域包含 内部范围包含变数 变数的参照储存在变数 当内部范围结束时,尝试存取 Rust编译器将丢掷一个编译错误,因为 Rust将使用借用检查器确定程式码无效。`a` `b` `10` `b` `a` `a` `a` 28 | 29 | ## 借用检查器 30 | 31 | 借用检查器用于解决悬挂参照的问题。借用检查器用于比较范围以确定它们是否有效。 32 | 33 | ![img](https://tw511.com/upload/images/201910/20191014013947407.png) 34 | 35 | 在上面的例子中,注释了 在编译时,Rust将拒绝该程式,因为 可以修复上面的程式码,以便不会发生编译器错误。`a` `a` `b` `b` `a` `b` 36 | 37 | ![img](https://tw511.com/upload/images/201910/20191014013947408.png) 38 | 39 | 在上面的例子中,因此,上面的程式码执行时没有任何编译错误。`a` `b` 40 | 41 | ## 生命周期注释语法 42 | 43 | - 生命周期注释不会改变任何参照的生存时间。 44 | - 函式还可以使用泛型生存期引数接受任何生命周期的参照。 45 | - 生命周期注释描述了多个引数的生命周期之间的关系。 46 | 47 | **生命周期注释语法应遵循的步骤:** 48 | 49 | - 生命周期引数的名称应以(`'` 50 | - 它们主要是小写和简写。例如:`'a` 51 | - 生命周期引数注释放在参照的`&` 52 | 53 | **生命周期注释语法的一些范例:** 54 | 55 | - `&i32` // reference 56 | - `& 'a i32` // reference with a given lifetime. 57 | - `& 'a mut i32` // mutable reference with a given lifetime. 58 | 59 | ## 函式签名中的生命周期注释 60 | 61 | ``` 62 | 'a`代表参考的生命周期。每个参考都有与之相关的生命周期。也可以在函式签名中使用生命周期注释。通用生命周期引数在角括号`<> 63 | ``` 64 | 65 | 范例 - 66 | 67 | ```rust 68 | fn fun<'a>(...); 69 | ``` 70 | 71 | 在上面的例子中,如果函式包含两个具有两个不同生命周期的参考引数,则它可以表示为:`fun` `'a` 72 | 73 | ```rust 74 | fn fun<'a,'b>(...); 75 | ``` 76 | 77 | 如果`'y'` 78 | 79 | ```rust 80 | fn fun<'a>(y : & 'a i32); 81 | ``` 82 | 83 | 如果`'y'` 84 | 85 | ```rust 86 | fn fun<'a>(y : & 'a mut i32); 87 | ``` 88 | 89 | 两个 唯一的区别是`&'a i32``&'a mut i32``'a``&``mut` 90 | 91 | `&mut i32`的意思是「对i32的可变参照」。表示「对具有生命周期'的 92 | `&'a mut i32` `i32` 93 | 94 | ## 结构中的生命周期注释 95 | 96 | 也可以在结构中使用显式生命周期,就像在函式中使用的一样。 97 | 98 | 下面来看看一个范例: 99 | 100 | ```rust 101 | struct Example 102 | x : & 'a i32, // x is a variable of type i32 that has the lifetime 'a. 103 | ``` 104 | 105 | 下面来看一个简单的例子: 106 | 107 | ```rust 108 | struct Example<'a> { 109 | x: &'a i32, 110 | } 111 | fn main() { 112 | let y = &9; 113 | let b = Example{ x: y }; 114 | println!("{}", b.x); 115 | } 116 | ``` 117 | 118 | 执行上面范例程式码,得到以下结果 - 119 | 120 | ```shell 121 | 9 122 | ``` 123 | 124 | ### impl块 125 | 126 | 可以实现具有生命周期`'a` `impl` 127 | 128 | 下面来看一个简单的例子: 129 | 130 | ```rust 131 | struct Example<'a> { 132 | x: &'a i32, 133 | } 134 | impl<'a> Example<'a> 135 | { 136 | fn display(&self) 137 | { 138 | print!("Value of x is : {}",self.x); 139 | } 140 | } 141 | fn main() { 142 | let y = &90; 143 | let b = Example{ x: y }; 144 | b.display(); 145 | } 146 | ``` 147 | 148 | 执行上面范例程式码,得到以下结果 - 149 | 150 | ```shell 151 | Value of x is : 90 152 | ``` 153 | 154 | ## 多个生命周期 155 | 156 | 有两种可能性: 157 | 158 | - 多个参照具有相同的生命周期。 159 | - 多个参照具有不同的生命周期。 160 | 161 | 当参照具有相同的生命周期时。 162 | 163 | ```rust 164 | fn fun <'a>(x: & 'a i32 , y: & 'a i32) -> & 'a i32 165 | 166 | //block of code. 167 | ``` 168 | 169 | 在上述情况下,参照`x` `y` `'a` 170 | 171 | 当参照具有不同的生命周期时。如下 - 172 | 173 | ```rust 174 | fn fun<'a , 'b>(x: & 'a i32 , y: & 'b i32) 175 | 176 | // block of code. 177 | ``` 178 | 179 | 在上述情况下,参考`x` `y` `'a` `'b` 180 | 181 | **'static** 182 | 183 | `'static`的生命周期是特殊的生命周期。它表示某些东西具有生命周期 主要是 具有「静态生命周期」的参照对整个程式有效。`'static` `'static` 184 | 185 | 范例: 186 | 187 | ```rust 188 | let s : & 'static str = "Yiibai tutorial" ; 189 | ``` 190 | 191 | ## 生命周期椭圆 192 | 193 | 生命周期椭圆是一种推理演算法,它使常见的模式更符合人体工程学。生命周期椭圆使一个程式被淘汰。 194 | 195 | 生命周期椭圆可以在任何地方使用: 196 | 197 | - `& 'a T` 198 | - `& 'a mut T` 199 | - `T<'a>` 200 | 201 | 生命周期椭圆可以以两种方式出现: 202 | 203 | - **输入生命周期** 204 | - **输出生存期** 205 | 206 | 范例 - 207 | ```rust 208 | fn fun<'a>( x : & 'a i32); // input lifetime 209 | fn fun<'a>() -> & 'a i32; // output lifetime 210 | fn fun<'a>(x : & 'a i32)-> & 'a i32; // Both input and output lifetime. 211 | ``` 212 | -------------------------------------------------------------------------------- /入门秘笈/Rust的特点.md: -------------------------------------------------------------------------------- 1 | # Rust的特点 2 | 3 | Rust是一种系统程式设计语言,Rust提供以下功能: 4 | 5 | - 零成本抽象 6 | - 错误讯息 7 | - 移动语意 8 | - 没有资料竞争的执行绪 9 | - 模式匹配 10 | - 保证记忆体安全 11 | - 高效的C系结 12 | - 安全的记忆体空间分配 13 | - 最少的时间 14 | 15 | #### 1.零成本抽象 16 | 17 | 在Rust中,可以新增抽象而不会影响程式码的执行时效能。它提高了程式码品质和程式码的可读性,而无需任何执行时效能成本。 18 | 19 | #### 2.错误讯息 20 | 21 | 在C++程式设计中,与GCC相比,错误讯息有了很好的改进。在清晰的情况下,Rust更进一步提高。错误讯息显示为(格式,颜色),并在程式中建议拼写错误。 22 | 23 | #### 3.型别推断 24 | 25 | Rust提供了型别推断的功能,这意味着它可以自动确定表示式的型别。 26 | 27 | #### 4.移动语意 28 | 29 | Rust提供此功能,允许在源物件是临时物件时,通过移动操作替换复制操作。 30 | 31 | #### 5.没有资料争用的执行绪 32 | 33 | 资料争用是两个或多个执行绪存取同一记忆体位置的条件。由于所有权系统,Rust提供了没有资料争用的执行绪功能。所有权系统仅将不同物件的所有者传输到不同的执行绪,并且两个执行绪永远不能拥有具有写存取许可权的相同变数。 34 | 35 | #### 6.模式匹配 36 | 37 | Rust提供了模式匹配的功能。在模式匹配中,Rust中的模式与'match'表示式一起使用,以更好地控制程式的控制流。以下是一些模式的组合: 38 | 39 | - 字面量 40 | - 阵列,列举,结构或元组 41 | - 变数 42 | - 万用字元 43 | - 预留位置 44 | 45 | #### 7.保证记忆体安全 46 | 47 | Rust通过使用所有权的概念保证了记忆体安全。所有权是C语言的记忆体控制和java的垃圾收集之间的中间地带。在Rust程式中,记忆体空间由变数拥有,并由其他变数暂时借用。这允许Rust在编译时提供记忆体安全性,而不依赖于垃圾收集器。 48 | 49 | #### 8.高效的C系结 50 | 51 | Rust提供了「高效C系结」的功能,这意味着Rust语言能够在与自身对话时与C语言进行互操作。Rust提供了一个「外部功能介面」来与C API进行通讯,并利用其所有权系统同时保证记忆体安全。 52 | 53 | #### 9.安全的记忆体空间分配 54 | 55 | 在Rust中,记忆体管理是手动的,即程式员可以明确控制分配和释放记忆体的位置和时间。在C语言中,使用 此运算子将智慧指标返回为 智慧指标是一种特殊的值,用于控制何时释放物件。智慧指标是「智慧的」,因为它们不仅跟踪物件的位置,而且还知道如何清理它。`malloc``~``int` 56 | -------------------------------------------------------------------------------- /入门秘笈/Rust第一个程式.md: -------------------------------------------------------------------------------- 1 | # Rust第一个程式 2 | 3 | 在本文中,使用Rust语言编写简单的程式,以了解如何编写,储存和编译Rust程式。现在,开启记事本档案并编写以下程式码: 4 | 5 | ```rs 6 | fn main(){ 7 | println!("Hello, world!"); 8 | } 9 | ``` 10 | 11 | 将上面内容储存到一个档案:`rustc hello.rs` 12 | 13 | ```shell 14 | Hello, world! 15 | ``` 16 | 17 | - `main()`:函式用大括号 函式不包含任何引数,也不返回任何值。`main()``main()``{}``main()` 18 | - `println!`:这是一个Rust巨集。如果它呼叫该函式,则它不包含符号:`'!'` 19 | - `"Hello World"`:它是作为引数传递给`println!` 20 | 21 | ## 建立,编译和执行程式的过程 22 | 23 | 1. 开启记事本档案并将程式码写入记事本档案中。 24 | 2. 使用`.rs` 25 | 3. 开启命令提示字元 26 | 4. 设定目录的路径,假设专案位于`/home/hema/worsp/rust` 27 | 5. 使用`rustc` 28 | 6. 最后,使用命令`./filename` 29 | 30 | ```shell 31 | hema@yiibai:~/worsp/rust$ rustc hello.rs && ./hello 32 | Hello World! 33 | ``` 34 | 35 | > 注:如果有遇到「error: could not exec the linker`link.exe` 36 | -------------------------------------------------------------------------------- /入门秘笈/Rust简介.md: -------------------------------------------------------------------------------- 1 | # Rust简介 2 | 3 | Rust程式设计语言旨在提供更好的记忆体安全性,但它仍处于维护过程中。 4 | 5 | ## Rust是什么? 6 | 7 | - Rust是由Mozilla员工「Graydon Hoare」于2006年开发的系统程式设计语言。他将这种语言描述为支援功能和命令正规化的「安全,并行和实用的语言」。 8 | - Rust的语法类似于C++语言。 9 | - Rust是免费的开源软体,即任何人都可以自由使用该软体,并且公开共用原始码,以便人们也可以改进软体的设计。 10 | - Rust在2016年,2017年和2018年的堆叠溢位开发者调查中被宣布为「最受欢迎的程式设计语言」之一。 11 | - 没有像 这意味着,记忆体由Rust内部管理。`calloc``malloc` 12 | 13 | ## Rust的使用者有哪些? 14 | 15 | 出于多种原因,Rust语言对许多人来说是理想的。 16 | 17 | 下面来看看吧: 18 | 19 | - **开发团队 低阶程式设计程式码包含需要测试人员进行大量测试的错误。但是,在Rust的情况下,如果程式包含错误,编译器拒绝编译程式码。通过与编译器并行工作,开发人员可以专注于程式的逻辑而不是专注于错误。** 20 | - **学生 Rust团队正在努力使普通人更容易理解系统概念,特别是那些不熟悉程式设计的人。** 21 | - **公司 这些任务包括命令列工具,Web服务,DevOps工具,嵌入式装置,音讯和视讯分析和转码,加密货币,生物资讯学,搜寻引擎,物联网应用程式,机器学习,甚至Firefox Web浏览器的重要部分。** 22 | - **开源开发人员 因此,他们可以使用原始码来改进Rust的设计。** 23 | -------------------------------------------------------------------------------- /入门秘笈/Rust结构体.md: -------------------------------------------------------------------------------- 1 | # Rust结构体 2 | 3 | 结构体是使用者定义的资料型别,由不同资料型别的变数组成。通过在结构体名称之前使用 结构体成员包含在大括号内。在大括号内,结构体成员定义了它们的名称和型别,结构成员也称为栏位。`struct` 4 | 5 | 结构体语法: 6 | 7 | ```rust 8 | struct Student 9 | { 10 | member-variable1; 11 | member-variable2; 12 | . 13 | . 14 | } 15 | ``` 16 | 17 | 在上面的语法中,结构体是使用关键字 结构体包含不同型别的变数。`struct` 18 | 19 | 宣告结构体的范例 - 20 | 21 | ```rust 22 | let user = Student{ 23 | // key:value pairs; 24 | } 25 | ``` 26 | 27 | 在上面的宣告中,它通过使用结构名称然后使用大括号来定义。大括号包含键:值对,其中键是栏位的名称,`user``Student``value` 28 | 29 | 下面程式码建立一个员工结构体: 30 | 31 | ```rust 32 | struct Employee{ 33 | employee_name : String, 34 | employee_id: u64, 35 | employee_profile: String, 36 | active: bool, 37 | } 38 | ``` 39 | 40 | 员工结构体范例: 41 | 42 | ```rust 43 | let employee = Employee{ 44 | employee_name : String::from("Akshay Gupta"), 45 | employee_id: 12, 46 | employee_profile : String::from("Computer Engineer"), 47 | active : true, 48 | }; 49 | ``` 50 | 51 | **如何存取结构体的成员变数?可以使用点( 假设想要存取** 52 | `.``Employee``employee_name` 53 | 54 | ```rust 55 | employee.employee_name; 56 | ``` 57 | 58 | > 注意:如果想通过使用点表示法来更改特定栏位的值,那么必须使范例可变,因为Rust不允许特定栏位为可变栏位。 59 | 60 | ```rust 61 | let mut employee = Employee{ 62 | employee_name : String::from("Akshay Gupta"), 63 | employee_id: 12, 64 | employee_profile : String::from("Computer Engineer"), 65 | active : true, 66 | }; 67 | employee.employee_name = String :: from("Akhil Gupta"); 68 | ``` 69 | 70 | 在函式体中建立范例: 71 | 72 | ```rust 73 | fn create_employee(name:String, profile:String) 74 | { 75 | Employee{ 76 | employee_name:name, 77 | employee_id:12, 78 | employee_profile:profile, 79 | active:true, 80 | } 81 | } 82 | ``` 83 | 84 | 在上面的范例中,在函式体中隐式建立了 函式返回具有给定名称和组态档案的`Employee``create_employee()``Employee` 85 | 86 | 当传递给函式和栏位的引数具有相同名称时,使用栏位初始化简写。 87 | 88 | 当变数和栏位具有相同的名称时,Rust提供了使用栏位初始化简写的灵活性。不需要重复栏位和变数。 89 | 90 | ```rust 91 | fn create_employee(employee_name:String, employee_profile:String) 92 | { 93 | Employee{ 94 | employee_name, 95 | employee_id:12, 96 | employee_profile, 97 | active:true, 98 | } 99 | } 100 | ``` 101 | 102 | 在上面的范例中,引数和栏位的名称相同。因此,不需要编写`employee_name:employee_name``employee_name` 103 | -------------------------------------------------------------------------------- /入门秘笈/Rust结构体方法语法.md: -------------------------------------------------------------------------------- 1 | # Rust结构体方法语法 2 | 3 | 方法类似于函式,因为它们在 方法还包含引数和返回值。但是,当在 这些方法的第一个引数始终是`start``then``fn``struct``self` 4 | 5 | ## 定义方法 6 | 7 | 在`struct` 8 | 9 | ```rust 10 | struct Square 11 | { 12 | a : u32, 13 | } 14 | impl Square 15 | { 16 | fn area(&self)->u32 17 | { 18 | self.a * self.a 19 | } 20 | } 21 | 22 | fn main() 23 | { 24 | let square = Square{a:10}; 25 | print!("Area of square is {}", square.area()); 26 | } 27 | ``` 28 | 29 | 执行上面范例程式码,得到以下结果 - 30 | 31 | ```shell 32 | Area of square is 100 33 | ``` 34 | 35 | 当在`struct``impl` 36 | 37 | ```rust 38 | impl Square 39 | { 40 | fn area(&self)->u32 41 | { 42 | self.a * self.a 43 | } 44 | } 45 | ``` 46 | 47 | 第一个引数是签名中的`self` 48 | 49 | 在这里,使用方法语法来呼叫 方法语法是一个范例,后跟点运算子,方法名称,引数和任何引数。`area()` 50 | 51 | ```rust 52 | square.area(); 53 | square`是范例,`area() 54 | ``` 55 | 56 | > 注意:如果想要更改呼叫该方法的范例,那么使用`&mut self``&self` 57 | 58 | **方法语法的优点:** 59 | 60 | 使用方法语法而不是函式的主要优点是,与范例相关的所有资料都放在`impl``impl` 61 | -------------------------------------------------------------------------------- /入门秘笈/Rust结构体更新语法.md: -------------------------------------------------------------------------------- 1 | # Rust结构体更新语法 2 | 3 | 使用 当新范例使用旧范例的大部分值时,可以使用 考虑两名员工`Struct` 4 | `struct update``employee1``employee2` 5 | 6 | - 首先,建立`Employee``employee1` 7 | 8 | ```rust 9 | let employee1 = Employee{ 10 | employee_name : String::from("Maxsu"), 11 | employee_id: 12, 12 | employee_profile : String::from("IT工程師"), 13 | active : true, 14 | }; 15 | ``` 16 | 17 | - 其次,建立 范例的某些值与 有两种方法可以宣告 第一种方法是在没有语法更新的情况下宣告`employee2``employee2``employee1``employee2` 18 | `employee2` 19 | 20 | ```rust 21 | let employee2 = Employee{ 22 | employee_name : String::from("Maxsu"), 23 | employee_id: 11, 24 | employee_profile : employee1.employee_profile, 25 | active : employee1.active, 26 | }; 27 | ``` 28 | 29 | 第二种方法是使用语法更新宣告`employee2` 30 | 31 | ```rust 32 | let employee2 = Employee{ 33 | employee_name : String::from("Yiibai"), 34 | employee_id: 11, 35 | ..employee1 36 | }; 37 | ``` 38 | 39 | 语法`..` 40 | 41 | 下面来看一个结构的简单范例: 42 | 43 | ```rust 44 | struct Triangle 45 | { 46 | base:f64, 47 | height:f64, 48 | } 49 | 50 | fn main() 51 | { 52 | let triangle= Triangle{base:20.0,height:30.0}; 53 | print!("Area of a right angled triangle is {}", area(&triangle)); 54 | } 55 | 56 | fn area(t:&Triangle)->f64 57 | { 58 | 0.5 * t.base * t.height 59 | } 60 | ``` 61 | 62 | 执行上面范例程式码,得到以下结果 - 63 | 64 | ```shell 65 | Area of a right angled triangle is 300 66 | ``` 67 | 68 | 在上面的例子中,建立了三角形( 三角形(`Triangle``Triangle``main()` 69 | -------------------------------------------------------------------------------- /入门秘笈/Rust错误处理.md: -------------------------------------------------------------------------------- 1 | # Rust错误处理 2 | 3 | 错误处理是Rust确定出错的可能性并确认在程式码进行编译之前采取某些操作的机制。此机制使程式更加健壮,因为能够在部署生产程式码之前发现并处理错误。Rust程式设计语言不包含异常。 4 | 5 | Rust中有两种型别的错误: 6 | 7 | - 不可恢复的错误。 8 | - 可恢复的错误。 9 | 10 | ![img](https://tw511.com/upload/images/201910/20191014013935392.png) 11 | 12 | - **可恢复的错误:完全停止该过程的可恢复错误并不严重。它由 可恢复错误的范例是「找不到档案」。是通用引数。这是一种值,在成功的情况下返回一个'OK'变数。这是一种错误型别,在具有**`Result ``T&E` 13 | `T->` 14 | `E->``Err` 15 | - **不可恢复的错误:例如:「除以零」是不可恢复错误的范例。**`!` 16 | 17 | #### 可恢复错误与不可恢复错误 18 | 19 | 可恢复错误是可以某种方式恢复的错误,而不可恢复错误是无法以任何方式恢复的错误。下面来看一下预期行为的情景: 20 | 21 | ``` 22 | "100".parse(); 23 | ``` 24 | 25 | 在上述情况下,因此,它是一个可恢复的错误。`"100"` 26 | 27 | **意外的行为** 28 | 29 | ![img](https://tw511.com/upload/images/201910/20191014013935393.png) 30 | 31 | **assert! 如果它不正确和错误,则程式停止执行。** 32 | 33 | 下面来看一个简单的例子: 34 | 35 | ```rust 36 | fn main() 37 | { 38 | let x : bool = false; 39 | assert!(x==true); 40 | } 41 | ``` 42 | 43 | 执行上面范例程式码,得到以下结果: 44 | 45 | ![img](https://tw511.com/upload/images/201910/20191014013935394.png) 46 | 47 | 在上面的例子中,因此,在执行时`x` `false` `assert!` `assert!` `panic!` 48 | 49 | **unreachable! 此巨集很有用,因为编译器无法确定无法存取的程式码。在执行时由** 50 | 51 | 下面来看一个简单的例子: 52 | 53 | ```rust 54 | enum Value 55 | { 56 | Val, 57 | } 58 | 59 | fn get_number(_:Value)->i32 60 | { 61 | 5 62 | } 63 | fn find_number(val:Value)-> &'static str 64 | { 65 | match get_number(val) 66 | { 67 | 7 => "seven", 68 | 8=> "eight", 69 | _=> unreachable!() 70 | } 71 | } 72 | 73 | fn main() 74 | { 75 | println!("{}", find_number(Value::Val)); 76 | } 77 | ``` 78 | 79 | 执行上面范例程式码,得到以下结果 - 80 | 81 | ![img](https://tw511.com/upload/images/201910/20191014013936395.png) 82 | 83 | 在上面的范例中,因此,`get_number()` `5` `unreachable!` `panic!` 84 | -------------------------------------------------------------------------------- /入门秘笈/匹配运算子.md: -------------------------------------------------------------------------------- 1 | # 匹配运算子 2 | 3 | 匹配运算子允许将值与一系列模式进行比较,并在找到匹配项时执行程式码。模式可以是文字值,变数名称,万用字元和许多其他内容。 4 | 5 | 下面通过一个简单的例子来理解匹配运算子: 6 | 7 | ```rust 8 | enum Computerlanguage 9 | { 10 | C, 11 | Cplus, 12 | Java, 13 | Csharp, 14 | } 15 | fn language(language:Computerlanguage) 16 | { 17 | match language 18 | { 19 | Computerlanguage::C=> println!("C language"), 20 | Computerlanguage::Cplus=> println!("C++ language"), 21 | Computerlanguage::Java=> println!("Java language"), 22 | Computerlanguage::Csharp=> println!("C# language"), 23 | } 24 | } 25 | fn main() 26 | { 27 | language(Computerlanguage::C); 28 | language(Computerlanguage::Cplus); 29 | language(Computerlanguage::Java); 30 | language(Computerlanguage::Csharp); 31 | } 32 | ``` 33 | 34 | 执行上面范例程式码,得到以下结果 - 35 | 36 | ```shell 37 | C language 38 | C++ language 39 | Java language 40 | C# language 41 | ``` 42 | 43 | 在上面的范例中,匹配运算子将语言的值与匹配运算子块中给出的表示式匹配。`Computerlanguage``C``Cplus``Java``Csharp` 44 | 45 | ## 与选项T匹配 46 | 47 | 当想要在某些情况下获得`T``` 48 | 49 | 选项 `` 50 | 51 | - None:表示失败或缺少值。 52 | - 一些(值):它是一个用T包装值的元组结构。 53 | 54 | 通过下面一个例子来理解: 55 | 56 | ```rust 57 | fn main() 58 | { 59 | even_number(2); 60 | even_number(3); 61 | } 62 | fn even_number(n:i32) 63 | { 64 | let num=n; 65 | match checked_even(n) 66 | { 67 | None=>println!("None"), 68 | 69 | Some(n)=> 70 | { 71 | if n==0 72 | { 73 | println!("{} is a even number",num); 74 | } 75 | else 76 | { 77 | println!("{} is a odd number",num); 78 | }}, 79 | } 80 | } 81 | fn checked_even(number:i32)->Option 82 | { 83 | 84 | Some(number%2) 85 | 86 | } 87 | ``` 88 | 89 | 执行上面范例程式码,得到以下结果 - 90 | 91 | ``` 92 | 2 is a even number 93 | 3 is a odd number 94 | ``` 95 | 96 | ## 匹配详尽 97 | 98 | 在Rust中,匹配是详尽的,即,应该尽可能地使程式码有效。假设忘记编写`None` 99 | 100 | 通过下面一个例子来理解: 101 | 102 | ```rust 103 | fn main() 104 | { 105 | Some(5); 106 | } 107 | fn Value(n:Option) 108 | { 109 | match n 110 | { 111 | Some(n)=>println!("{}is a Number",n), 112 | } 113 | } 114 | ``` 115 | 116 | 编译输出结果如下 - 117 | 118 | ![img](https://tw511.com/upload/images/201910/20191014013923386.png) 119 | -------------------------------------------------------------------------------- /文章/Rust 与 C++:深入的语言比较.md: -------------------------------------------------------------------------------- 1 | 2 | ![img](https://pic2.zhimg.com/80/v2-cb004bb5ed725791c973268745967d76_720w.png) 3 | 4 | 5 | 6 | Rust 与 C++ 是开发人员最近的热门话题。Rust 和 C++ 之间有很多相似之处,许多开发人员想知道使用哪个**更好**(特别是对于系统编程语言)。 7 | 8 | 这两种语言都在系统级开发领域竞争,并且与 Python 等对初学者更友好的语言相比,它们的学习曲线都很陡峭。 9 | 10 | 在选择编程语言时,您应该考虑其针对特定用例的效率和生产力。在本指南中,我们将深入研究 Rust 和 C++,比较和对比这些语言的用途、优点和缺点。 11 | 12 | **本指南一目了然:** 13 | 14 | - 什么是Rust? 15 | - 什么是 C++? 16 | - 技术对比 17 | - 架构 18 | - 游戏开发 19 | - 结论和总结 20 | 21 | ![img](https://pic3.zhimg.com/80/v2-871ebc3fba575da987cff3fcb1510da7_720w.png) 22 | 23 | ## 什么是Rust ? 24 | 25 | Rust 是由 Mozilla 开发的多范式编程语言,专注于性能和安全性。Rust 以其先进的**安全并发能力**而闻名 。Rust 的语法类似于 C++,但它提供了更快的速度和内存安全性,不使用垃圾收集器。 26 | 27 | > Rust 最初是为 Mozilla Firefox 浏览器开发的,但它的效率和优势吸引了许多 C++ 开发人员开始使用 Rust,通常用于游戏开发。 28 | 29 | Rust 在**内存管理**方面是创新的。例如,它不允许空指针或悬空指针。由于其功能性,Rust 常用于构建设备驱动程序、嵌入式系统、游戏和操作系统,例如 BlogOS、Redox、RustOS、Rux 和 Tock。 30 | 31 | Rust 代码可以说以其速度和在测试前调试代码的能力而闻名。例如,Rust 可以帮助您开发在运行时检查代码错误的程序。 32 | 33 | ### Rust 的显着特点 34 | 35 | - 内存管理 36 | - 内存安全 37 | - 所有权制度 38 | - 多态性 39 | - 速度和性能 40 | 41 | ```rust 42 | fn main() { 43 | println!("Hello World!"); 44 | } 45 | ``` 46 | 47 | ![img](https://pic2.zhimg.com/80/v2-94868a9913dfc568cb08850ddfadebba_720w.png) 48 | 49 | ## 什么是 C++? 50 | 51 | C++是一种高级、通用的编译语言,已经存在一段时间了。由于其语法复杂,C++代码用于需要高速和并发的程序。C++ 以帮助您真正接近金属而闻名。 52 | 53 | > C++ 是 C 的扩展,因此它继承了许多相似之处,但偏向于嵌入式软件和大型系统。 54 | 55 | 它以其性能、稳健性和效率而闻名。C++ 提供了对系统及其内存的大量控制。C++ 是**构建**Microsoft Windows 等操作系统和视频游戏开发的主要语言,因为一些游戏开发框架是用 C++ 编写的。 56 | 57 | C++ 还提供了一个丰富的标准库,称为标准模板库。有了它,可以轻松构建从 GUI 应用程序到桌面应用程序,再到 3D 图形和游戏的所有内容。 58 | 59 | ### C++的显着特点 60 | 61 | - 面向对象 62 | - C++ 模板 (STL) 63 | - 运算符重载 64 | - 遗产 65 | - Lambda 表达式 66 | 67 | ```c++ 68 | #include 69 | using namespace std; 70 | 71 | int main() { 72 | // your code goes here 73 | cout << "Hello World"; 74 | return 0; 75 | } 76 | ``` 77 | 78 | ## 技术比较 79 | 80 | 那么,为什么要在 C++ 上使用 Rust,或者反过来呢?如果两者都是**高性能**、开源且功能强大的,那么更好的选择是什么?让我们深入了解他们的技术组件。 81 | 82 | 从高层次上看,C++ 拥有更大的社区、更广泛的用例、更多的框架,并且在任何编码公司中都得到了很好的认可。另一方面,由于其静态类型特性,Rust 在安全性、速度和防止不正确/不安全的代码方面更好。 83 | 84 | > Rust 非常擅长防止可能导致未定义行为的数据竞争,而 C++ 无法为您完成这项工作并会打开漏洞。 85 | 86 | ### 内存安全 87 | 88 | 大多数系统级语言不提供自动内存管理,因为垃圾收集等功能会降低性能。为了保持速度,C++ 牺牲了内存安全性,这是一个显着的缺点。 89 | 90 | 最近对 C++ 的更新具有诸如**RAII(资源获取即初始化)之**类的新功能,以摆脱手动内存管理,但它们并没有解决底层的核心问题。 91 | 92 | 为了解决这个问题,Rust 使用了一个**所有权系统**,它全面强制并提高了其内存安全性。它基本上消除了对任何手动内存管理程序的需要。Rust 为管理过程提供了内置功能,而 C++ 则留给您。 93 | 94 | ### 指针 95 | 96 | 在计算机科学中,指针是存储内存地址的对象。换句话说,地址“指向”程序中的其他数据。智能指针是具有附加元数据和功能的数据结构。大多数高级和低级语言都有某种指针功能。 97 | 98 | C ++提供了类型 std::shared_ptr和std::unique_ptr可以像智能指针使用。Rust 在其标准库中有几个智能指针,比如引用计数智能指针类型。 99 | 100 | Rust 和 C++ 都以对象的形式(String在 Rust 或std::stringC++ 中)大量使用智能指针,并提供了许多有用的附加功能。 101 | 102 | ### 编译时间 103 | 104 | C++ 和 Rust 的完整构建时间大致相同,具体取决于 C++ 项目正在实现的模板数量(模板越多,速度越慢)。C++ 通常在增量编译方面做得更好。Rust 的编译器以友好而著称。它提供了有用的错误消息和一流的工具。 105 | 106 | ### 便于使用 107 | 108 | 大多数同时使用 Rust 和 C++ 的人都说 Rust 更易于使用,因为它**具有明确定义的语义**以及防止不需要/未定义行为的能力。同样,C++ 具有如此多的功能,因此很难跟踪。由于 C++ 向您展示了幕后发生的事情,因此 C 程序员需要很好地理解它。 109 | 110 | ## 框架和库 111 | 112 | 尽管 Rust 比 C++ 年轻,但它们都提供了出色的框架和库,尽管 C++ 库往往更通用一些。这里的区别在于,C++ 不像 Java、C# 或 JavaScript 那样是框架驱动的环境,因此它们不会被普遍使用。 113 | 114 | 然而,在 Rust 中,有几个框架可以提供功能性、安全性和健壮性的代码,例如: 115 | 116 | - **Rocket:**用于提高安全性、速度和灵活性的 Rust Web 框架。 117 | - **Nickel:**一个 Rust 框架,用于开发具有明确验证规则的用户友好的信息流控制系统 118 | - **Azul:**一个基于 Rust 的即时模式 GUI 框架,用于开发桌面应用程序 119 | 120 | 在库方面,主要的 C++ 库是标准库,它是类和函数的集合。它提供了几个通用容器、操作容器的函数、通用字符串和流(包括交互式和文件 I/O)以及其他语言支持。 121 | 122 | > 虚幻引擎是一个用 C++ 编写的框架,用于游戏开发。 123 | 124 | ## 游戏开发 125 | 126 | 目前,C++是游戏开发的主要语言。大多数市场主导的游戏都是用 C++ 编写的,而用 C++ 编写的虚幻引擎是游戏开发的主要框架。虚幻引擎是完善、完善和成熟的。 127 | 128 | Rust 也**进入了游戏开发领域**,但它没有提供与框架相同的功能。游戏可以用 Rust 开发,但要在这个领域与 C++ 竞争还需要一些时间。随着越来越多的 Rust 开发人员构建 Rust 生态系统,它可能会开始更加激烈地竞争。 129 | 130 | 因此,如果您对游戏开发感兴趣,请继续学习 C++,但要密切关注 Rust,尤其是现在Rust Foundation的创建。 131 | 132 | ### 用户界面 133 | 134 | UI 开发是 C++ 和 Rust 比较的热门领域,尽管这两种语言都不是 UI 开发的首选。但是,他们的表现如何? 135 | 136 | C++ 提供了 GTKmm,它是 GTK+ C 库的现代接口。Rust 提供了 Azul,一个我们上面提到的开源、即时模式的 GUI 框架。它更新、更现代,拥有活跃的社区。 137 | 138 | ## 结论和总结 139 | 140 | 那么,哪个更好?两种编程语言都有其独特的优点和缺点。 141 | 142 | - C++ 在社区支持方面更好。如果你想要一个可靠的、支持良好的语言和一个强大的库,C++ 是一个不错的选择。您还应该使用 C++ 进行**游戏开发**。 143 | - Rust 更适合内存安全和并发。Rust 也更容易学习和使用。如果您希望代码**非常安全**并**避免内存泄漏**,那么 Rust 是您的最佳选择。 144 | 145 | > 归根结底,您选择的语言取决于您的舒适度。选择 Rust 或 C++ 不会让你失望。两者都是可靠的、使用良好的、公认的语言,可以完成工作。 146 | -------------------------------------------------------------------------------- /文章/基于Rust的Android Native内存分析方案.md: -------------------------------------------------------------------------------- 1 | ## 基于Rust的Android Native内存分析方案 2 | 3 | 原文链接:[高德技术](https://mp.weixin.qq.com/s?__biz=Mzg4MzIwMDM5Ng==&mid=2247485845&idx=2&sn=a0fc676b9a7a5e8d0453cd219b8d9345&utm_source=tuicool&utm_medium=referral) 4 | 5 | 高德地图车机版运行的车载系统环境绝大部分都是基于安卓的定制系统,且高德车机版底层代码均为C/C++ Native代码。因此,在安卓上需要有一种通用的Native内存性能分析方案。 6 | 7 | **背景**高德地图车机版运行的车载系统环境绝大部分都是基于安卓的定制系统,且高德车机版底层代码均为C/C++ Native代码。因此,在安卓上需要有一种通用的Native内存性能分析方案。内存塔(MemTower)是一个基于开源项目memory-profiler并移植安卓且优化改进后的方案,解决了之前方案存在的痛点问题,满足了通用Native内存性能分析需求。该项目采用Rust语言编写,并利用了Rust的一些特性来完成对Native内存访问的Hook. 8 | 9 | **1. Android Native内存分析痛点与诉求** 10 | 11 | 这一节主要介绍我们为什么要做这件事以及对于这件事我们期望达到什么样的目标。 12 | 13 | **1.1 现有工具缺陷** 14 | 15 | Android在Java层面有很完善的性能分析工具,但是在Native层面没有完整的解决方案。主要表现在: 16 | 17 | - 不支持Android 4.x,线上统计数据显示4.x版本的车机仍占有较大比重,因此这点成为了无法忽视的问题。 18 | - 安卓自带的malloc_debug功能在不同的版本上行为不同,而且车机安卓系统大多经过了系统厂商的定制,不能保证这些功能可用。 19 | 20 | 因此, 无法基于Android系统自有的功能做到Native内存性能分析。 21 | 22 | 我们团队之前也在这方面做出了一些成果,但还是存在下面几个问题: 23 | 24 | - 通过修改编译参数对Native代码函数入口/结束位置插桩来进行Hook,导致了性能严重下降; 25 | - 由于是侵入式分析,对内存问题分析需要单独编译出包分析,解决效率大幅降低,一个内存泄漏问题的排查成本按天计算。 26 | - 缺少精准内存使用数据。 27 | 28 | **1.2 打造一套完整的Native内存性能分析方案** 29 | 30 | 结合上门的问题痛点,我们希望能够有一套完整的Native内存性能分析方案。具体诉求表现在下面几点: 31 | 32 | - 支持安卓4.x在内的绝大多数安卓系统。 33 | - 无侵入式分析,内存问题的发现与精准定位同时完成。 34 | - 性能优异,overhead低。 35 | - 支持长时间内存泄漏压测。包括车厂客户在内的研发团队都会对导航进行压测,需要能够支持长时间的压测并定位内存泄漏问题。 36 | - 函数级内存使用数据。原先的方案重点在于解决内存泄漏的问题,获取的内存使用数据不够精确。而我们希望新的方案能够获得详细的内存使用数据,用来支持内存性能优化。 37 | 38 | **2. 内存塔(MemTower)方案** 39 | 40 | 本节主要介绍memory-profiler项目的实现和内存塔(MemTower)方案在移植该项目至Android平台上的过程和对原方案的改进。阐述我们是如何实现并满足上述的诉求。 41 | 42 | **2.1 选择Rust & Memory-profiler** 43 | 44 | 针对上门的诉求,期望能够找到一种新的解决方案。当时正好在研究Rust,因此在GitHub上结合关键字搜索便发现了memory-profiler(以下简称mp)项目,作者koute是前Nokia工程师。接着才有了后面的内存塔。本节主要阐述mp如何结合Rust实现内存Profile的相关原理和功能。 45 | 46 | **2.1.1 Hook实现** 47 | 48 | 通常对Native内存性能分析使用的方案是Hook malloc 和 free 等内存调用请求。mp的原理也是如此,利用LD_PRELOAD 预加载自定义库实现对内存操作函数的Hook。这种方案最大的问题是容易引发循环malloc调用。如下图,Hook了程序内存请求后,Hook业务自身的内存请求也会触发内存请求,从而造成了malloc循环调用,引发栈崩溃。 49 | 50 | [![img](https://s5.51cto.com/oss/202101/16/1b2c725d0f29d49cfd77fcfc0d3018c3.webp)](https://s5.51cto.com/oss/202101/16/1b2c725d0f29d49cfd77fcfc0d3018c3.webp) 51 | 52 | mp的做法利用了Rust的可自定义内存分配器(Allocator)的特性,将曾经的Rust默认内存分配器jemalloc作为自定义分配器,并在jemalloc-sys的c代码中将最终的内存申请mmap替换成自定义的函数入口(从而也区分应用和自身的mmap调用),最终调用mmap系统调用。 53 | 54 | [![img](https://s4.51cto.com/oss/202101/16/5b8a05c3ae2db0e334a7d20db8a2a408.webp)](https://s4.51cto.com/oss/202101/16/5b8a05c3ae2db0e334a7d20db8a2a408.webp) 55 | 56 | 将Rust内存请求转发给系统调用后,还需要将应用的内存请求继续传递给系统libc. mp的做法是通过Rust的feature开关,可以自行选择两种方式处理应用内存请求,这两种方式都是通过在Rust中指定link_name 属性实现: 57 | 58 | - 直接通过__libc_malloc的link_name将应用内存请求转发给libc 59 | - 通过指定成jemallocator的函数入口 _rjem_malloc,使应用和Rust共用jemalloc. 60 | - 最终可以使Hook业务使用完整的Rust语言功能而不用担心Rust自身代码引起的循环调用崩溃。 61 | 62 | **2.1.2 高性能堆栈反解** 63 | 64 | 除了利用Rust系统编程语言特性避开内存循环调用之外,作者还利用Rust的高性能特点实现了几种高性能堆栈反解。 65 | 66 | 利用ELF的.eh_frame 节(C++异常处理机制)提供的栈回溯信息。 67 | 68 | 基于.ARM.exidx + .ARM.extab的栈回溯,这个是ARM提供的unwind table. 69 | 70 | 具体实现可以看作者的这个Crate not-perf。这里选择第二种做说明,如图下,对每个线程的堆栈都用线程局部存储维护了一套栈帧缓存,这个缓存来自于ELF文件中的unwind table信息,当堆栈的帧在缓存未命中时会把对应二进制的unwind表被加载到内存,而命中的时候,就不需要去读取文件。通常二进制被加载后它的地址空间就不会发生变化,所以缓存的效率很高。缺点是每个线程都有一套完整的缓存。从系统层面看占用的内存overhead很大。 71 | 72 | [![img](https://s3.51cto.com/oss/202101/16/ad046c2912248a4b7bbd7e735ba2a0c5.webp)](https://s3.51cto.com/oss/202101/16/ad046c2912248a4b7bbd7e735ba2a0c5.webp) 73 | 74 | **2.1.3 强大的数据分析功能** 75 | 76 | 从mp的页面可以看到它除了内存Profile外,还有一个对应的数据分析Server端,采用actix-web框架,且具备一个非常强大的分析功能。主要特性有下面几点: 77 | 78 | - 内存使用量和泄漏两种视角的时序曲线非常直观。 79 | - 搭配了一个非常强大的过滤器,可以实现针对内存生命周期、函数、时间等多维度做过滤查询及其对应的内存火焰图功能。 80 | - 所有功能具备RESTful API接口,可以非常容易的实现定制。 81 | 82 | 详细的使用说明这里不做过多的介绍。 83 | 84 | [![img](https://s6.51cto.com/oss/202101/16/5bc52d4509520490f755ee7435a3ccba.webp)](https://s6.51cto.com/oss/202101/16/5bc52d4509520490f755ee7435a3ccba.webp) 85 | 86 | 87 | 88 | 89 | 90 | [![img](https://s3.51cto.com/oss/202101/16/e1cdb53eaf76a0b2302650c17999ea59.webp)](https://s3.51cto.com/oss/202101/16/e1cdb53eaf76a0b2302650c17999ea59.webp) 91 | 92 | **2.2 移植** 93 | 94 | 了解完mp的基本原理后,本节我们主要阐述在移植安卓平台过程中遇到的各种问题(坑)。 95 | 96 | **2.2.1 自定义Allocator** 97 | 98 | mp的Hook方案在Android平台上存在较多问题,主要体现在下面几点: 99 | 100 | - Jemalloc本身也才是Android 5.0开始引入安卓,mp自带的jemalloc-sys会导致一个应用里存在两个jemalloc,最终表现为在不同的版本上有着各种各样的异常崩溃,问题排查成了阻碍。 101 | - __libc_malloc是glibc提供的malloc函数入口别名,但在Android平台没有对应这类实现。 102 | 103 | 因此,我们采用最原始的dlsym 方法获取内存相关函数入口,再将其封装成Rust Allocator. 应用的内存请求也使用这些函数地址。如下图,最终所有内存请求都传给libc,这样Rust的业务代码对libc来说是透明的。 104 | 105 | [![img](https://s3.51cto.com/oss/202101/16/a0280381be1c58e2f171aa95ae74242a.webp)](https://s3.51cto.com/oss/202101/16/a0280381be1c58e2f171aa95ae74242a.webp) 106 | 107 | **2.2.2 栈回溯** 108 | 109 | 栈回溯这块同样有一些移植修改。上面说到作者提供了基于C++异常处理机制的栈回溯方法,但是这个方案要求依赖C++库。而C在Android 8.0之后才会成为默认依赖。这要求在8.0之前的版本运行时应用必须也依赖C++库。因此我们移除了这个栈回溯方案,舍去了这个依赖。 110 | 111 | **2.2.3 地址空间重载** 112 | 113 | 在程序启动或调用dlopen/dlclose时链接器会加载(或卸载)ELF文件,相应的,程序的地址空间会发生变化,这时候栈回溯缓存里的地址空间就可能会失效,需要重新加载(reload),reload操作扫描整个地址空间的变更,这个成本很高。与此同时还需要一种低成本获取地址空间变化的方式. mp的实现主要有两种方式: 114 | 115 | libc提供的接口dl_iterate_phdr. Android API_LEVEL低于21(即5.0之前)没有,5.0之后这个函数的结构体和在高版本Android的实现不同。所以Rust定义的单一C结构体格式会导致读取到脏数据作为reload依据,导致非常高频繁地reload.; 116 | 117 | Perf的 PERF_RECORD_MMAP2 事件,这个要求内核版本大于3.16。因此这在Android 4.x上也不具备。 118 | 119 | [![img](https://s6.51cto.com/oss/202101/16/51426839a7f27876f32de5e9dfca0477.webp)](https://s6.51cto.com/oss/202101/16/51426839a7f27876f32de5e9dfca0477.webp) 120 | 121 | 实际运行过程中程序在加载完所有依赖ELF后,地址空间几乎很少再变。因此,我们修改为只有在新的ELF被加载时才进行地址空间重载。火焰图结果显示可以大幅降低Hook时的计算成本。 122 | 123 | **2.3 改进** 124 | 125 | 到目前为止, 内存塔已经可以在支持 LD_PRELOAD 的Android版本上正确运行了(含4.x)。但是上面诉求中还有一点无法满足:长时间内存泄漏压测。而且在数据分析过程中,我们希望有更多维度的信息。因此,本小节主要介绍我们对内存塔的改进。 126 | 127 | **2.3.1 内存泄漏压测** 128 | 129 | mp原先的定位正如它的名称表述,是一款内存性能分析工具,它记录的是全量内存信息。这点决定了它的数据量规模。在长时间压测一小时的多个业务场景中,根据内存使用量不同,生成的采样数据文件有1GB~7GB之多。这样的数据量无法满足业务的需要。 130 | 131 | 因此,我们增加了内存泄漏检测模式(ONLY_LEAKED),这个模式的原理如下: 132 | 133 | - 将记录到内存开辟的每一层栈帧记录到一个字典树(Trie Tree)中,同时记录开辟的内存大小。 134 | - 内存释放时更新字典树对应的节点信息。当前泄漏是否达到某个阈值(如100MB), 是则停止采样。 135 | - 在结束采样时把整个字典树存储的未释放内存记录写入文件。 136 | 137 | 这种模式的优点是最终的数据量非常的小,实际压测一小时数据文件大小在100~200MB之间。再进过mp自带的postprocess 子命令压缩后,大小不足100MB。不足之处是内存塔需要在内存中缓存一个全量的堆栈历史数据,当没有新的栈帧记录出现后这个内存增长才会趋于稳定。 138 | 139 | **2.3.2 增强分析过滤器** 140 | 141 | 导航的业务模块划分和线程很多,因此增加了按线程和库正则筛选过滤器选项。 142 | 143 | [![img](https://s4.51cto.com/oss/202101/16/e15177ea845893f93e9467dc4eb6d9ab.webp)](https://s4.51cto.com/oss/202101/16/e15177ea845893f93e9467dc4eb6d9ab.webp) 144 | 145 | **2.3.3 内存火焰图完善** 146 | 147 | mp原方案的内存火焰图是以内存大小(allocated)作为火焰图维度,在分析内存性能时内存开辟次数(allocations)也是一个很重要的指标,因此加入内存开辟次数火焰图。这是当初最早改进的功能,而且火焰图的形状类似塔状,就把该项目重命名为:内存塔(MemTower)。 148 | 149 | 最后一点是原方案的火焰图信息没有以线程为单位划分,我们把堆栈信息按线程区分后会更加直观。 150 | 151 | **分配次数火焰图** 152 | 153 | [![img](https://s3.51cto.com/oss/202101/16/e5bff766b002c680e93403497b7ffbca.webp)](https://s3.51cto.com/oss/202101/16/e5bff766b002c680e93403497b7ffbca.webp) 154 | 155 | **分配大小火焰图** 156 | 157 | [![img](https://s5.51cto.com/oss/202101/16/4a81e88f94ce068a2021b03929a9cb7e.webp)](https://s5.51cto.com/oss/202101/16/4a81e88f94ce068a2021b03929a9cb7e.webp) 158 | 159 | **3. 内存塔的能力及更多可能** 160 | 161 | 最后一节介绍下内存塔提供了什么样的能力、收益以及还有哪些可能。 162 | 163 | **3.1 能力** 164 | 165 | 内存塔(MemTower)在Android 8.0以下依赖setprop wrap.com.xxx.xxx 和 root权限的能力,8.0以上版本如果没有root权限还可以通过配置Android项目wrap.sh来加载内存塔库。另外,由于mp原生支持Linux的原因,我们也成功适配了奔驰戴姆勒这类嵌入式Linux项目车机。 166 | 167 | - 支持平台:Android 4.x、5.1.1和7或更高以上版本(5.0和6系统存在Bug, 无法设置setprop ). Linux x86_64, AArch64, Arm. 168 | - 采样方式: 非侵入式. 非Root设备可选侵入式方式。 169 | - 采样模式: 常规性能分析模式和内存泄漏压测模式。 170 | - 特点: 高性能堆栈反解、完善的内存分析Insight体验(多维度过滤器分析、内存火焰图等)。 171 | 172 | 原先发现内存泄漏问题重新出包二次压测分析,再推断可能泄漏点的流程耗费时间按天计算。利用内存塔(MemTower)做一遍测试后几分钟即可解析出精细化数据,大幅降低了内存性能问题分析成本。mp提供的这套Hook思路和高性能堆栈反解其实可以不仅仅局限在内存方面的分析,还可以针对IO性能分析或其它问题上。 173 | -------------------------------------------------------------------------------- /文章/理解 Rust 的生命周期.md: -------------------------------------------------------------------------------- 1 | # 理解 Rust 的生命周期 2 | 3 | 作者:丹尼尔·P·克拉克 4 | 5 | 原文链接:https://www.cloudbees.com/blog/lifetimes-in-rust 6 | 7 | 高级语言很方便地处理我们代码中的每个对象的存活的范围(`scope`), 我们不需要理解这些对象的生命周期。Rust同样为我们管理着生命周期,我们可以通过所有权(`ownership`)和借用(`borrowing`)对简单情况进行更多的控制,但是对于复杂的情况,我们需要在代码中给出识别标识,以便编译器能够理解更大的生命周期的范围。 8 | 9 | 简单的说,一切的一切归根结底都是为了在对象使用完之后就释放它。高级语言如Go、Ruby、Python等等,使用垃圾回收器在整个代码中扫描和标记对象,以查看它们是否准备好从内存中释放掉,并将对所有已标记可释放的对象执行释放操作。当你不再使用对象时,低级语言如C、汇编要求你手工释放它们。 10 | 11 | Rust避免了垃圾回收和手写代码释放内存的成本,它根据代码库中每个对象的生命周期维护释放内存的时间。生存期主要由所有权系统决定(描述代码的哪个部分负责拥有内存中对象的系统),以及在复杂情况下,由帮助编译器而提供的手动生命周期描述符来决定。一旦对象的生命周期束,内存将立即释放。 12 | 13 | ## 简单的生命周期 14 | 15 | Rust的**const**类型的生命周期是整个程序,它的值可以内联到代码中的任何地方。 16 | 17 | ```rust 18 | const MAJOR_VERSION: i32 = 1; 19 | ``` 20 | 21 | **static**类型的生命周期也是整个程序,但它不会被内联,它存在于内存的固定位置。 22 | 23 | ```rust 24 | static MINOR_VERSION: i32 = 0; 25 | ``` 26 | 27 | 大多数其他对象的生命周期只发生在块(`block`)的范围内,或者直到某个方法调用夺走了它们的所有权。如果一个对象要在方法调用中超出其使用范围而存在(意思是方法调用完还继续存活),那么该方法需要借用(`borrow`)它,或者复制(`copy`)它,以便在方法完成后,它的生命周期可以在外部作用域中继续长存。 28 | 29 | ```rust 30 | let money: String = "42".to_string(); 31 | fn borrow_it(qty: &String) { 32 | println!("Your money total is ${}", qty) 33 | } 34 | borrow_it(&money); // borrowed ownership 35 | // the ownership of money has been returned to this higher scope 36 | fn consume_it(qty: String) { 37 | println!("My money total is ${}", qty) 38 | } 39 | consume_it(money); 40 | // money memory is freed as the ownership has been 41 | // taken into the methods scope and that scope has ended. 42 | println!("No money: ${}", money); 43 | // This fails 44 | ``` 45 | 46 | 当我们运行上面的代码的时候,Rust会告诉我们哪里出错了: 47 | 48 | ```rust 49 | error[E0382]: use of moved value: `money` 50 | --> src/main.rs:19:29 51 | | 52 | 15 | consume_it(money); 53 | | ----- value moved here 54 | ... 55 | 19 | println!("No money: ${}", money); 56 | | ^^^^^ value used here after move 57 | | 58 | = note: move occurs because `money` has type `std::string::String`, which does not implement the `Copy` trait 59 | ``` 60 | 61 | 请注意,它告诉我们,如果`std::string::String`如果实现了`Copy trait`,我们的代码就可以工作。如果您将上述代码更改为使用`i32`类型而不是String,它将正常地工作;`i32`确实实现了`Copy trait`,编译器将从块中的用法推断出该值稍后将被使用,因此在这种情况下,将在借用时执行复制。即使复制后,money的生命周期也会在最后一次使用时结束,因为它会被最后的`println!`命令所使用。 62 | 63 | ## 复杂的生命周期 64 | 65 | 有时候,当代码中没有足够的信息来确定生命周期时,Rust编译器会要求描述/注释生命周期。 66 | 67 | ```rust 68 | // 地球 69 | #[derive(Debug)] 70 | struct Earth { 71 | location: String, 72 | } 73 | // 恐龙 74 | #[derive(Debug)] 75 | struct Dinosaur<'a> { 76 | location: &'a Earth, 77 | name: String, 78 | } 79 | fn main() { 80 | let new_york = Earth { 81 | location: "New York, NY".to_string(), 82 | }; 83 | let t_rex = Dinosaur { 84 | location: &new_york, 85 | name: "T Rex".to_string(), 86 | }; 87 | println!("{:?}", t_rex); 88 | } 89 | ``` 90 | 91 | 在上面的例子中,你可以看到一个生命周期的注释`'a`。当我们的struct借用`Earth`实例的时候, 它需要增加生命周期标识,它会帮助编译器理解🦕恐龙(`Dinosaur`)不能比🌍地球(`Earth`)还长寿,因为它引用了Earth。 92 | 93 | 当我第一次在自己的项目中处理实现和学习生命周期的时候,有一个技巧帮助了我。当程序建议需要它们时,就是在它们可能不需要放置的地方放置了更多的生命周期引用。我发现编译器的错误消息在“生命周期注释存在并且错误时”比“不存在和错误时”更能理解我的意图。当然,我建议查看实现了生存期的代码,以帮助您开始工作。一点点的尝试和错误将帮助您快速理解。 94 | 95 | 上面恐龙的一个示例`impl`代码如下: 96 | 97 | ```rust 98 | impl<'a> From> for String { 99 | fn from(d: Dinosaur) -> String { 100 | format!("{:?}", d) 101 | } 102 | } 103 | // replace the above println! with 104 | println!("{}", String::from(t_rex)); 105 | ``` 106 | 107 | ## 范围生命周期 108 | 109 | 当需要从一个底层的或者内部(lower/inner)的scope中获取值时, 最好的方法就是把需要的结果值赋值给更高的scope中的变量: 110 | 111 | ```rust 112 | { 113 | // outer scope 114 | let result: i32; 115 | { 116 | // inner scope 117 | result = 42 + 42; 118 | } 119 | println!("{}", result); 120 | } 121 | ``` 122 | 123 | 如果我们尝试在内部的scope中将结果直接赋值给外部的变量而没有预先声明它,我们会得到如下的错误: 124 | 125 | ```rust 126 | error[E0425]: cannot find value `result` in this scope 127 | --> src/main.rs:10:18 128 | | 129 | 10 | println!("{}", result); 130 | | ^^^^^^ not found in this scope 131 | ``` 132 | 133 | 这是因为在inner scope中对象的生命周期只限于inner scope, 除非它们被赋值给外部的更长的scope中的对象。返回值可以看作是外部的scope的对象。我们改造一下上面的例子: 134 | 135 | ```rust 136 | { 137 | let result: i32 = { 138 | 42 + 42 139 | }; 140 | println!("{}", result); 141 | } 142 | ``` 143 | 144 | 正常输出 84。 145 | 146 | 当我们没有正确使用scope时编译器会洞悉到我们的错误。所以我们直接写我们认为正确的代码就好了,简单按照编译的反馈信息修改我们的错误就好了,这里有个错误的例子: 147 | 148 | ```rust 149 | { 150 | let result: &i32; 151 | 152 | { 153 | let x = 42 + 42; 154 | result = &x; 155 | } 156 | println!("{}", result); 157 | } 158 | ``` 159 | 160 | 编译它: 161 | 162 | ```rust 163 | error[E0597]: `x` does not live long enough 164 | --> src/main.rs:7:3 165 | | 166 | 6 | result = &x; 167 | | - borrow occurs here 168 | 7 | } 169 | | ^ `x` dropped here while still borrowed 170 | ... 171 | 10 | } 172 | | - borrowed value needs to live until here 173 | ``` 174 | 175 | 这里输出很清晰的生命周期图。或者使用`clone`或者使用`copy`等手段可以把值返回给更高的scope。但是这经常会带来一些性能上的影响因为复制内存中的数据要比传引用要化更长的时间。 176 | 177 | ## 总结 178 | 179 | 在Rust所有涉及生命周期的事情中,注释似乎是一个很大的障碍,因为语法看起来有点过时。但重要的是,当你使用它们的时候,你不会改变它们的方式——你其实只是简单地宣布它们。也就是说,有注释的生命周期与没有写注释的生命周期的工作方式是相同的。它们只是帮助编译器澄清生命周期所涉及的上下文的标记。 180 | 除此之外,生命周期很简单。只需编写代码,看看会发生什么。Rust语言的编译器将是您的导师,您的理解将随着您从编译器非常智能的错误消息中学习而增长。你可以大胆地编码,因为Rust可以帮助你在未知的海洋中遨游。 181 | --------------------------------------------------------------------------------