├── README.md ├── doc ├── Rusts-core-competitiveness.pdf ├── rust-runtime-zh.md └── why-rust-is-reliable.asciidoc └── learn-rust-2024.md /README.md: -------------------------------------------------------------------------------- 1 | learn-rust 2 | ========== 3 | -------------------------------------------------------------------------------- /doc/Rusts-core-competitiveness.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liigo/learn-rust/5214eb7a8aeb47dd32a5e577007e82854de0f8b5/doc/Rusts-core-competitiveness.pdf -------------------------------------------------------------------------------- /doc/rust-runtime-zh.md: -------------------------------------------------------------------------------- 1 | # Rust运行时指南 2 | 3 | [A Guide to the Rust Runtime][source], by Alex Crichton and Brian Anderson 4 | [source]: http://static.rust-lang.org/doc/master/guide-runtime.html 5 | 6 | 翻译:庄晓立(Liigo),com.liigo@gmail.com, [G+][g],[Weibo][w],[CSDN][c],[Rust中文圈][r] 7 | 8 | 日期:2014年2月。 9 | 10 | [g]: https://plus.google.com/+LiigoZhuang 11 | [w]: http://weibo.com/liigo 12 | [c]: http://blog.csdn.net/liigo 13 | [r]: https://plus.google.com/communities/100629002107624231185 14 | 15 | > 2015年5月20日译者Liigo注:此文形成于Rust 1.0之前的开发动荡期,目前已经严重过时(outdated)!相关设施在Rust 1.0标准化过程中发生了巨大变化(参见[RFC #230](https://github.com/rust-lang/rfcs/blob/master/text/0230-remove-runtime.md)),Runtime已经不存在了。特此声明,以免误导读者。 16 | 17 | Rust编程语言的标准发行版包含两个运行时库(libgreen和libnative),提供I/O等基础设施的统一接口。但对Rust语言本身而言,运行时(runtime)并不是必需的;Rust编译器可以生成在所有环境中运行的代码,包括内核(kernel)环境。Rust语言也不需要运行时提供内存安全,因为它的类型系统本身已经足够安全——通过编译时静态验证给予保证。运行时只是利用语言的安全特性提供一系列便利的、安全的、高层的抽象。 18 | 19 | 如果Rust没有运行时(runtime),我们编程能做的事情非常有限,所以Rust需要提供运行时。这份指导手册将探讨Rust用户空间(user-space)的运行时、如何使用它、它能做什么。 20 | 21 | ## 1、什么是运行时? 22 | 23 | Rust运行时可以被视为提供以下功能代码的组合:输入/输出(I/O)、任务孵化(task spawning)、任务本地存储(TLS)等等。本质上,它提供一少部分对象,为实现常见功能提供便利支持。Rust运行时自身的实现是自包含的(self-contained),避免干扰其他库。 24 | 25 | 运行时目前提供以下功能特性(不完整列表): 26 | 27 | - 输入/输出(I/O) 28 | - 任务孵化(task spawning) 29 | - 消息传递(message passing) 30 | - 任务同步(task synchronization) 31 | - 任务本地存储(TLS, task-local storage) 32 | - 日志(logging) 33 | - 本地堆(local heaps)(GC heaps) 34 | - 任务展开(task unwinding) 35 | 36 | ### 1.1、运行时的目标是什么? 37 | 38 | 运行时的设计初衷是达成以下目标: 39 | 40 | - Rust库能够在多种环境中运行,而不需要关心各种环境的具体细节。经常被提及的两种环境是M:N和1:1。Rust运行时最初首先支持M:N,现在也同时支持了1:1。 41 | - Rust运行时在达成在多种环境中运行的目标时,不需要强制区分不同的编译模式。一个库被编译一次就能在多种不同的环境中永久运行,是我们明确的设计目标。 42 | - Rust运行时应当高效运行。在其架构设计上,不应该有阻止程序高效运行的障碍。但也不是说非得在任何情况下都必须以最快的速度运行。 43 | - Rust运行时应当尽可能对用户透明。不鼓励用户直接与运行时交互。 44 | 45 | ## 2、运行时的体系结构 46 | 47 | 本节将介绍目前的Rust运行时的体系结构。Rust运行时曾经被重写了几遍,本节仅涉及当前最新版本。 48 | 49 | ### 2.1、本地任务(a local task) 50 | 51 | Rust运行时的核心抽象概念是任务(Task)。任务代表了运行Rust代码的“线程”,但此“线程”并不一定直接对应于操作系统里的线程。运行时里的大多数服务都是通过Task提供给用户,因而可以做到单个任务内部决策。 52 | 53 | 采用这种策略的结果是,要求所有使用标准库的Rust代码,都有一个本地的Task结构体(local Task structure)。该结构体被存储在操作系统的线程局部存储(TLS, Thread Local Storage)内部,以便高效访问。 54 | 55 | 一定有这么一个Task结构体存在,是Rust运行时本质上唯一的假定。这是一个核心假定,令所有使用标准库的代码受益,因此Task被定义在标准库内。几乎所有运行时服务都是通过Task提供的。 56 | 57 | ### 2.2、输入/输出(I/O) 58 | 59 | 当处理I/O时,通常有一些约定俗成的方法,但这些方法未必在任何情况下都正确。I/O的处理非常复杂,几乎不可能在多种环境中使用一致的处理方案。不能保证Rust任务(Task)有权限处理I/O,也不能保证它以何种方式处理I/O。 60 | 61 | 这意味着,标准库中无法定义处理I/O功能的具体实现代码,只能定义一批I/O操作接口,由各环境下的Task各自实现具体功能。这些I/O接口被设计为以同步I/O调用为核心。此架构不会根本性的阻碍以其他形式处理I/O,但目前还没有别的处理方式。 62 | 63 | 运行时(runtime)必须实现的这些I/O接口被定义在std::rt::rtio模块内。注意这些接口是不稳定的,是不对用户公开的(仅作为标准库内部实现细节)。 64 | 65 | (译者Liigo注:任务的接口被定义在标准库libstd中,任务的具体实现被定义在运行时库libgreen/libnative中。) 66 | 67 | ### 2.3、任务孵化(Task spawning) 68 | 69 | 任务(Task)的一项常见操作是,孵化(spawning)一个子任务(child task),在其中执行某些工作。这意味着并行执行被启用。如何孵化子任务,没有一个统一方法(未在标准库中定义),由各(运行时内的)任务自行决定。 70 | 71 | 任务孵化被解释为“孵化一个子任务(原文为sibling,疑为child之笔误)”,其高层操作接口定义在std::task模块中。孵化子任务前,可以事先设定子任务的参数,运行时的实现必须依据这些参数,执行具体的孵化行为。 72 | 73 | 任务的另一个操作是处理自身的运行状态,如阻塞(block)和唤醒(wake up)任务。具体操作细节由任务自己决定,标准库未做规定。 74 | 75 | ### 2.4、运行时接口(trait Runtime)和任务结构体(struct Task) 76 | 77 | 运行时的所有特性都被定义在接口`Runtime`和结构体`Task`。在不同运行时库(libgreen、libnative)中,结构体Task都是相同的,而接口Runtime的实现各不相同。Task内部存储了Runtime接口的实现对象,因而可以调用其接口函数。 78 | 79 | ## 3、运行时的实现(implementations) 80 | 81 | Rust发行版提供了两个运行时库,分别是1:1线程模型的libnative和M:N线程模型的libgreen。就像许多计算机科学问题一样,你很难说选择哪个运行时库是正确的,它们各自都有优势和劣势。下面分别介绍两个运行时库提供的功能和没有的功能,供程序员参考并自行决定选择使用哪一个。 82 | 83 | ### 3.1、1:1 - 使用libnative 84 | 85 | libnative运行时库的实现,是基于操作系统本地线程,加上libc阻塞I/O调用。因其用户空间的线程一一对应于操作系统线程,而被称为1:1线程模型。 86 | 87 | 在这种模型下,每一个Rust任务(Task)对应于一个操作系统线程,并且每一个I/O对象唯一对应一个文件描述符(fd)(或者其他系统内的对等物)。 88 | 89 | 使用libnative的一些优势: 90 | 91 | - 保证与FFI绑定(外部函数接口绑定)交互操作。即使你调用的外部C库函数(例如数据库驱动)阻塞在线程I/O,也不会干扰其他Rust任务(Task)正常执行(因为它们在不同的系统线程内)。 92 | 93 | - 在某些情况下相比M:N有更少的I/O损耗。并非所有M:N I/O都保证尽最大可能的快,而且有些东西(比如文件系统API)在某些平台下不是真正的异步操作,意味着M:N实现可能会比1:1实现引发更多损耗。 94 | 95 | ### 3.2、M:N - 使用libgreen 96 | 97 | 运行时库libgreen基于异步I/O框架libuv实现了“绿色线程”。M:N线程模型中的M是指当前进程内的操作系统本地线程个数,N是指Rust任务个数(即绿色线程个数)。在这种模型中,M个系统线程调度运行N个Rust绿色线程,在用户空间中进行线程上下文切换(context switching)。(译者Liigo注:通常情况下,N远大于M。) 98 | 99 | M:N模型中很重要的一点是,Rust任务不能使用同步系统调用,阻塞任务自身。一旦被阻塞,任务所属的系统本地线程就整个僵化,无法再运行其他Rus任务。这意味着M个本地线程被(暂时)废掉了一个(但还有M-1个本地线程继续工作,因而能够做到0死锁)。通过在底层调用异步I/O接口(但从用户使用的角度看仍然像同步接口),系统本地线程永远不会阻塞。 100 | 101 | libgreen库没有任何I/O实现,仅实现了Rust绿色线程的调度器(Schedulers)。真正的I/O实现位于libuv的封装库librustuv中。这么做的目的是希望将来会有不依赖libuv的I/O实现版本(当然目前还没有)。 102 | 103 | 使用libgreen的一些优势: 104 | 105 | - 任务孵化的速度快。在M:N模型中,孵化新任务(绿色线程)时可以完全避免系统调用,效率更高。 106 | 107 | - 任务切换的速度快。因为上下文切换是在用户空间进行的,所有任务间竞争操作(互斥、管道等)不用执行系统调用,因而速度更快。更高效的上下文切换也会促成更大的吞吐量。 108 | 109 | #### 3.2.1、调度器池(Pool of Schedulers) 110 | 111 | M:N线程模型基于以下思路构建:通过M个操作系统本地线程(在libgreen中被称为M个调度器,它们共同组成一个调度器池),调度运行N个Rust任务(或称之绿色线程)。通过green::SchedPool类型可以细粒度地控制调度器池。SchedPool还是唯一能够孵化新的M:N任务的类型。新孵化的任务,跟当前任务一样,平等的从属于同一个调度器池。新任务必然持有调度器池的句柄,用于内部调用以便孵化其他任务。 112 | 113 | ### 3.3、选择哪一个? 114 | 115 | 既然有两个运行时库的实现,显然要做出决定选择使用哪一个。默认情况下,编译器总是链接其中之一。当前默认的运行时库是libgreen,但是今后默认的运行时库将会是libnative。 116 | 117 | 编译器默认选择链接一个运行时库,满足了用户的简单需求。而且这种默认行为不是强制性的,用户还可以自行选择使用哪个运行时库。 118 | 119 | 例如,这个程序将链接到默认运行时库: 120 | 121 | ``` 122 | fn main() {} 123 | ``` 124 | 125 | 然而下面这个程序就是由用户决定明确的链接到特定的运行时库(libgreen): 126 | 127 | ``` 128 | extern mod green; 129 | 130 | #[start] 131 | fn start(argc: int, argv: **u8) -> int { 132 | green::start(argc, argv, main); 133 | } 134 | 135 | fn main() {} 136 | ``` 137 | 138 | 两个运行时库libgreen和libnative都提供了上层的start函数,用于在各自运行时中启动初始的第一个Rust任务(Task)。 139 | 140 | ## 4、运行时在哪里? 141 | 142 | 运行时的源代码分散在以下多个地方: 143 | 144 | - [std::rt](http://static.rust-lang.org/doc/master/std/rt/index.html) 145 | - [libnative](http://static.rust-lang.org/doc/master/native/index.html) 146 | - [libgreen](http://static.rust-lang.org/doc/master/green/index.html) 147 | - [librustuv](http://static.rust-lang.org/doc/master/rustuv/index.html) 148 | 149 | 150 | ---------------- 全文完 ---------------- 151 | 152 | 译者Liigo注:这篇文章英文[原文][1]多有重复混乱处,而我限于英文水平和Rust技术水平,有时也不能完全理解原意。如有翻译不周,敬请谅解,并恳请指正。我的联系方式在本文开头。 153 | [1]: http://static.rust-lang.org/doc/master/guide-runtime.html 154 | 155 | 156 | 本文地址: 157 | 158 | - CSDN:http://blog.csdn.net/liigo/article/details/19249145 159 | - Github:https://github.com/liigo/learn-rust/blob/master/doc/guide-runtime-zh.md 160 | - Gdrive:https://docs.google.com/document/d/1uqW9BfPtop9_Nuj0akGRtotsjO0WfkJj3JZ-5gDLAds 161 | - Rust中文圈:https://plus.google.com/+LiigoZhuang/posts/5wAqgkJxq1m 162 | - PDF可打印版:https://github.com/liigo/learn-rust/raw/master/doc/guide-runtime-zh.pdf 163 | -------------------------------------------------------------------------------- /doc/why-rust-is-reliable.asciidoc: -------------------------------------------------------------------------------- 1 | = 为什么我说Rust是靠谱的编程语言 2 | Liigo Zhuang 3 | version 1.0, 2015. 4 | 5 | .... 6 | 作者:Liigo(庄晓立) 7 | 时间:2015年5月16日 8 | 原创链接:http://blog.csdn.net/liigo/article/details/45757123 9 | 版权声明:未经作者许可不得转载;授权转载需注明出处。 10 | .... 11 | 12 | **** 13 | **2016年2月22日修补说明**:本文最初发表至今已逾半年,这期间Rust语言蓬勃发展,版本从1.0升级到了1.6(1.7也近在咫尺),变化很大。现借《程序员》杂志3月刊发行之际对原文做一些修订和增补,其中增补部分在文中有明确标记。 14 | **** 15 | 16 | 序言:本文试图帮您解答“我要不要(投入大量时间和精力)学习Rust语言?”这个问题。作者尽量较少的谈及Rust语言本身,反而尝试从Rust语言周边入手,长时间、大范围、多角度地考察,研判Rust语言是否靠谱,并给出尽可能客观的理由。为写成本文,作者Liigo不惜“卧底”Rust“老巢”长达一年多,收集整理总结了大量信息。如果嫌长,可以只看小标题,粗略浏览一番。 17 | 18 | 19 | == Rust编程语言 20 | 21 | http://www.rust-lang.org/[Rust](http://blog.rust-lang.org/[blog])是一门强调安全、并发、高效的系统编程语言。其中四个关键词,系统编程、安全、并发、高效,是Rust语言的核心特征,也是区别于其他编程语言的首要因素。 22 | 23 | - Memory safety without garbage collection 24 | - Concurrency without data races 25 | - Abstraction without overhead 26 | 27 | 除此之外,我再补充一些关键词,以便读者更直观地了解Rust:静态类型/编译式语言/静态编译/动态编译、泛型/函数式/面向对象、模式匹配/ADT、DST/Associated Types/闭包(Closures)、Static/Dynamic/Multiple-Dispatch、 28 | 没有虚拟机(VM)、没有垃圾收集器(GC)、没有运行时(Runtime)、没有空指针/野指针/内存越界/缓冲区溢出/段错误、没有数据竞争(Data Race)…… 29 | 30 | Rust语言具有特性丰富、设计优良、适用范围广等诸多优点。 31 | 32 | 我(Liigo)从2013年底开始正式关注Rust项目,……至今有一年半了。其中有赞有批,有争有闹,也有贡献源码。本文所写的是我这些日子以来的所看、所闻、所感。 33 | 34 | 判断一门新的编程语言“是否靠谱”,是主观性很大的课题。Rust语言今日才刚刚发布1.0版本,它的未来发展走向如何,谁也说不清楚,说到底都是猜测。但是直觉告诉我,如果人靠谱、团队靠谱、技术能力靠谱、态度靠谱、社区靠谱,这个项目在很大程度上就是靠谱的、值得期待的。 35 | 36 | 谨以此文,献给我长久期待的 http://blog.rust-lang.org/2015/05/15/Rust-1.0.html[Rust 1.0]! 37 | 38 | == 开放、友好、高效的开源社区 39 | 40 | 相当彻底的开源项目,开放、透明、友好,进度热火朝天,动作大刀阔斧。这是我第一次亲身参与并观察到的如此大规模的开源编程语言项目的开发过程。(之前也关注过Go语言项目,但其规模要小得多。) 41 | 42 | - 开放源代码、GitHub/Git在线开发 https://github.com/rust-lang/rust 43 | - 开放系统设计过程,重要设计项目的提出、讨论、评估、决策均在线进行(https://github.com/rust-lang/rfcs[RFCs]) 44 | - 内部决策过程也公开透明,每周发布会议记录(https://github.com/rust-lang/meeting-minutes[meetimg-minutes]) 45 | - 公开接受第三方开发者提交的 https://github.com/rust-lang/rust/pulls[Pull Requests],必要时还指导开发 46 | - 有一个核心团队(http://www.rust-lang.org/team.html[the core team])负责项目的发展方向和最终决策 47 | - 有大量的(超过 https://github.com/rust-lang/rust/blob/master/AUTHORS.txt[1000] 人!)第三方开发者给Rust贡献源代码、文档和测试用例 48 | - 多次将优秀的第三方开发者吸纳进入官方开发团队和核心团队 49 | - 多次在世界各地(包括北京)主办和协办小型本地开发者见面会 50 | - https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust[IRC], http://internals.rust-lang.org[internals], https://reddit.com/r/rust[Reddit/r/rust], https://hn.algolia.com/?query=Rust&sort=byPopularity&prefix&page=0&dateRange=all&type=story[HN(Hacker News)], https://stackoverflow.com/questions/tagged/rust?sort=frequent[StackOverflow]有许多跟Rust相关的技术讨论,常见核心开发者参与其中 51 | - Github上用Rust语言开发的项目也风风火火(详见下文) 52 | 53 | “**热火朝天**”,用于形容其工程量大、进度快、成效显著。看看Rust的 https://github.com/rust-lang/rust/blob/master/RELEASES.md[Release Notes],常见这类字眼: 54 | 55 | - Version 1.0.0 (May 2015): ~1500 changes, numerous bugfixes 56 | - Version 1.0.0-alpha.2 (February 2015): ~1300 changes, numerous bugfixes 57 | - Version 1.0.0-alpha (January 2015): ~2400 changes, numerous bugfixes 58 | - Version 0.12.0 (October 2014): ~1900 changes, numerous bugfixes 59 | - Version 0.11.0 (July 2014): ~1700 changes, numerous bugfixes 60 | - Version 0.10 (April 2014): ~1500 changes, numerous bugfixes 61 | - Version 0.9 (January 2014): ~1800 changes, numerous bugfixes 62 | - Version 0.8 (September 2013): ~2200 changes, numerous bugfixes 63 | - ...... 64 | 65 | 还有很多就不一一列出了。Rust自从2012年1月20日发布0.1版,到现在的1.0正式版,平均每隔三个月发布一版,每次升级改进都多达一两千项。 66 | Rust是在GitHub/Git上在线开发的,开发者对源代码的每一项改动(commits)都被版本管理系统记录在案,有据可查。 67 | 大多数是实质性的功能升级,不存在靠修改标点、配置文件、拼写错误、或者每改三五行代码就提交的凑数行为(在此严重鄙视Atom编辑器、Kotlin语言)。 68 | 反而常见动不动就 https://github.com/rust-lang/rust/pull/16453[一] https://github.com/rust-lang/rust/pull/22172[次] https://github.com/rust-lang/rust/pull/16377[提] https://github.com/rust-lang/rust/pull/17669[交] https://github.com/rust-lang/rust/pull/21972[上] https://github.com/rust-lang/rust/pull/21759[千] https://github.com/rust-lang/rust/pull/20482[行] 甚至 https://github.com/rust-lang/rust/pull/13901[上] https://github.com/rust-lang/rust/pull/13700[万] 行 Rust 代码的情况, https://github.com/rust-lang/rust/pull/19448[例] https://github.com/rust-lang/rust/pull/18993[子] https://github.com/rust-lang/rust/pull/20179[比] https://github.com/rust-lang/rust/pull/18827[比] https://github.com/rust-lang/rust/pull/18967[皆] https://github.com/rust-lang/rust/pull/16156[是], https://github.com/rust-lang/rust/pull/14638[。] https://github.com/rust-lang/rust/pull/22971[。] https://github.com/rust-lang/rust/pull/21689[。] 69 | 70 | 有一个网站叫 http://this-week-in-rust.org["This Week in Rust"],每周进展公告,专门介绍Rust语言最近一周的最新重大变动,可供大家参考。里面的内容虽然不全,但颇有代表性。这个网站几经变迁,但是自2013年6月上线时起,两年来,作者cmr坚持每周更新,几乎从未中断。 71 | 72 | 总之我(Liigo)说Rust的开发“热火朝天”,一点也不夸张。(我还要顺便鄙视Apple公司,发布某某OS新版的时候,动不动就说“新增1500项API”,哎,咱还就较真儿了,去查,算上所有Function、所有Type、Type内的所有Method、所有常量定义—— #define XX 123,你懂的 ——勉强够数!跟Rust的 "~1500 changes" 相比,天上人间。) 73 | 74 | 大家可以比照近十年在中国大陆和近两年在南中国海的大型基建项目的进展速度,体会Rust那种热火朝天的开发场面。处于这样的开发环境下,所有人都深受鼓舞,所有人都知道,一切都会越来越好,知道所有的欠缺和困难都是暂时的。行动永远比语言有说服力。 75 | 76 | “**大刀阔斧**”,用于形容其开发行为豪迈、干脆,持续追求“更好的设计和实现”,无包袱、无迁就。 77 | 只要有了更好的设计(或实现),经过深入讨论和评估之后,果断替换掉旧的设计(或实现)。 78 | 不管这项改动有多复杂、多麻烦,也不理会因此形成的大量不兼容性,勇往直前的行动。 79 | 说去胳膊就去胳膊,说卸腿就卸腿,就是眼睛它也敢摘下来镶个火眼金睛再装回去。牵一发而动全身的事情,干了可不止一次。 80 | 例子有很多,最典型的是libgreen,之前Rust靠它一条腿走路,后来有了libnative,两条腿走路,再后来全都砍掉,最终做到没有运行时(Runtime)。 81 | 其他的例子还有std::io/os/path的大型重构(https://github.com/rust-lang/rfcs/blob/master/text/0517-io-os-reform.md[I/O OS] https://github.com/rust-lang/rfcs/blob/master/text/0474-path-reform.md[Path] Reform),重新设计然后无缝替换回去(有rustc、servo为证),可谓自己给自己做了大型手术。 82 | 一个新兴的项目,在真正面世之前的开发过程中,如果不经历几次这类大的阵痛,很难说它最终是成熟的和久经考验的。 83 | 如果因为各种顾虑而迁就、保留旧的设计(或实现),很难说最终的产品是完善的和设计优良的。 84 | 如果面世之前都不肯改进,面世定型之后改进的可能性就更小了(束手缚脚),缺陷可能伴随终生,令所有的用户长期的纠结。 85 | (这种大刀阔斧,与我(Liigo)当年在易语言公司参与研发EF语言时我所主张并践行的观点一致。有意推迟发布1.0也是为了给完善产品留足充裕的时间。) 86 | 87 | 需要强调的是,Rust开发者大刀阔斧的日子,只发生在Rust 1.0正式版发布之前。1.0之后,他们将老老实实的遵守 http://semver.org/lang/zh-CN/[SemVer 2.0] 规范,再也不会轻易做出破坏代码向后兼容性的行为。本文后面还会谈到这一点。 88 | 89 | == 十年勤耕不辍、低调做人高调做事 90 | 91 | 2006年,创始人Graydon Hoare启动了Rust编程语言项目,利于业余时间开发了三年,完成Rust语言的第一个可用版本。早期的Rust编译器 https://github.com/rust-lang/rust/tree/ef75860a0a72f79f97216f8aaa5b388d98da6480/src/boot[rustboot] 是用OCaml语言开发的。这三年间发生的事情,我们现在知道的并不多。根据创始人对Rust的命名,可以一窥其设计初衷: 92 | ____ 93 | 我从很多名称中挑选出了"Rust"。主要受到病原菌的启发——那些令人惊讶的、生死轮回的、多源寄生的奇妙物种。而且"Rust"还有其他内涵:它很好地契合了“贴近金属”(bare metal)、“复古编程语言技术”的主题;它从字面上融合了"Trust"(信任)和"Robust"(健壮)。 —— Graydon Hoare 94 | ____ 95 | 96 | 2009年,Rust项目被Graydon Hoare赠送给(英文原文"was presented to")Mozilla公司,并得到持续活跃地开发支持。Mozilla创建了以Graydon为首的专业团队全职开发Rust,并且开放源代码。 97 | 98 | 2010年至2011年,Rust语言的编译器被用Rust语言重写,完成自举,采用LLVM作为编译后端——之前的Rust编译器是用OCaml语言编写的。 99 | 100 | 2012年1月发布0.1版,第一个面向公众的预览版本问世。从那时起,平均每3个月发布一个新版本,版本号每次只加0.1,改动的内容却往往天翻地覆。2012年到2015年这三年多的时间里,开发者持续不断的改进Rust语言、编译器和标准库,翻新重修,精益求精。不断地否定自己,不断地超越自己,一步一个里程碑。 101 | 102 | 2012年2月,也就是Rust 0.1刚刚发布不久, https://github.com/servo/servo[Servo]项目被创建,用Rust语言开发下一代浏览器引擎,目的在于验证Rust语言开发大型实用项目的能力。 103 | 104 | 2012年到2015年这三年多时间,Rust和Servo互相扶持着茁壮成长起来了。Mozilla公司在Rust和Servo这两个不盈利的开源项目上付出的大量人力物力财力和时间成本,体现了他们全力打造下一代全新系统编程语言的决心和气魄。但是他们很少花费精力在大规模宣传和营销上,导致大部分公众/开发者几乎从没听过Rust语言,仅靠长期的口碑相传吸引了一批慧眼识金的忠实的开发者。 105 | 106 | Rust不是富二代也不是官二代,它没有一个有钱或有权的爹。Mozilla公司,论资金规模和影响力,远远不及Google、Apple、Microsoft,勉强算是二流公司,但是它依然给予了Rust长期的坚定的支持。 107 | 108 | 历经近十年精心打造,Rust靠自身实力赢得未来。2015年5月16日,Rust正式发布1.0版本,破茧成蝶,吹响进入新时代的号角。 109 | 110 | 111 | == 定位精准而潜力广泛的应用领域 112 | 113 | 现今的软件系统开发,从底层到中层到上层,大致分为以下三个层次: 114 | 115 | - (底层)系统底层开发:裸金属(bare metal)、操作系统(OS)、内核(kernel)、内核模块(mod)等 116 | - (中层)系统应用开发:虚拟机(VM)、容器(Container)、数据库/游戏/Web/Ftp/Dns服务器、浏览器引擎、模拟器等 117 | - (上层)普通应用开发:编译器、浏览器、消息推送系统、Web应用系统、管理信息系统、其他等等 118 | 119 | 其中,(底层)系统底层开发,强调对底层硬件的控制;(中层)系统应用开发,对CPU和内存的占用十分敏感;(上层)普通应用开发,更倾向于方便快捷的开发效率。通常意义上所说的“系统编程”,往往是指中底层系统开发。 120 | 121 | Liigo认为,Rust语言足以胜任这三个层次的软件开发。理由是:Rust是静态类型的编译式语言,基于LLVM生成高度优化的代码,再加上没有垃圾收集器(GC)等额外的运行时开销,执行效率非常高,对内存的利用十分灵活,因而胜任(中层)系统应用开发;Rust具有丰富的语言特性,便捷的项目编译和依赖管理,充分可用的跨平台的标准库,因而胜任(上层)普通应用开发;Rust支持raw pointer、unsafte block、C ffi、asm!、No runtime,因而胜任(底层)系统底层开发。Rust语言特别强调并保证的内存安全,对于三个层次尤其是中底层,是额外的突出的加分项。 122 | 123 | 上面的论述偏向于理论,可能不如实践有说服力。下面我们看看现实中Rust已经做到了什么程度(不是能做什么,而是做了什么,咱们靠事实说话): 124 | 125 | - 底层开发: https://github.com/charliesome/rustboot[rustboot] https://github.com/ryanra/RustOS[rustos] https://github.com/thepowersgang/rust-barebones-kernel[barebones] http://www.reddit.com/r/programming/comments/342082/cs_honors_thesis_reenix_implementing_a_unixlike/[reenix] http://jvns.ca/blog/2014/03/12/the-rust-os-story/[5steps] https://github.com/rust-lang/rust-wiki-backup/blob/master/Operating-system-development.md[others] 126 | - 中层开发: https://github.com/servo/servo[Servo]浏览器引擎 https://github.com/PistonDevelopers/piston[Piston]游戏引擎 https://github.com/hyperium/hyper[Hyper]HTTP服务器 https://github.com/pcwalton/sprocketnes[SprocketNES]NES模拟器 https://github.com/nukep/llamadb[LlamaDB]数据库 127 | - 上层开发: https://github.com/rust-lang/rust/tree/master/src/librustc[Rustc]编译器 https://github.com/rust-lang/cargo[Cargo]项目管理 https://github.com/iron/iron[Iron]&https://github.com/nickel-org/nickel.rs[Nickel]Web开发框架 https://github.com/PistonDevelopers/conrod[Conrod]GUI库 128 | 129 | 早在2013年我(Liigo)开始关注Rust之前,那时候Rust还有可选的GC,还有不算小的Runtime,还有笨重的标准库。即使在那种情况下,都有人不断地尝试用Rust做底层开发(参见前面的链接)。后来,Rust有了几个大的动作,令其更加胜任系统底层开发工作: 130 | 131 | - 拆分标准库(std),提取出专门针对底层开发的极其轻量级的核心库(core) https://github.com/rust-lang/rfcs/blob/master/text/0040-libstd-facade.md[RFC #40] https://github.com/rust-lang/rust/issues/13851[Issue #13851: Make std a facade] https://github.com/rust-lang/rust/pull/13901[PR #13901: Refactor libcore out of libstd] https://github.com/rust-lang/rust/issues/11829[old] 132 | - 移除运行时库 https://github.com/rust-lang/rfcs/blob/master/text/0230-remove-runtime.md[RFC #230] https://github.com/rust-lang/rust/pull/18967[PR #18967: Finish runtime removal] https://github.com/rust-lang/rust/pull/17673[PR #17673: remove librustuv] https://github.com/rust-lang/rust/pull/18557[PR #18557: remove rtio] https://github.com/rust-lang/rust/pull/19654[PR #19654: remove librustrt] 133 | - 删掉GC https://github.com/rust-lang/rfcs/blob/master/text/0256-remove-refcounting-gc-of-t.md[RFC #256] https://github.com/rust-lang/rust/pull/17666[PR #17666] 134 | - 放弃分段式栈 https://mail.mozilla.org/pipermail/rust-dev/2013-November/006314.html[Abandoning segmented stacks in Rust] 135 | - 支持静态编译 https://github.com/mozilla/rust/pull/10528[PR #10528: Add static linking to rust] 136 | - 添加`#![no_std]`属性 http://doc.rust-lang.org/book/no-stdlib.html[no_std] 允许用户放弃使用(功能丰富但相对笨重的)标准库(std),选用更底层更轻量级的 http://doc.rust-lang.org/stable/core/index.html[core],libc,alloc,collections 等库,Option/Result/Iterator/Deref/Cell/String/Vec/HashMap等基础类型依然可用。更绝的是,你甚至可以连core也不用,纯裸奔(http://blog.csdn.net/liigo/article/details/39347541[参见本人旧作])。由此可见Rust为支持底层开发不遗余力。能做到这一地步的系统语言还真不多见。 137 | 138 | Rust是名副其实的系统编程语言,在这个领域,它不惧怕跟任何对手竞争。向下,Rust可取代C语言地位;居中,Rust可挑战C++市场,向上,Rust可向Java、Python分一杯羹。总之,Rust精准定位于中底层系统应用开发,上可攻下可守,适用范围相当广泛,具有全能型选手的潜质。开发者们学习Rust语言,不怕没有用武之地。 139 | 140 | 141 | == 自举(用Rust语言开发Rust编译器) 142 | 143 | Rust在2010年至2011年完成自举,使用Rust语言开发出Rust编译器rustc, https://github.com/rust-lang/rust/commit/6997adf76342b7a6fe03c4bc370ce5fc5082a869/[取代了]之前用OCaml语言开发的Rust编译器rustboot。Rust标准库,很早就是Rust语言写的。这意味着,早在四年前,Rust早期核心开发人员,就已经是全职的Rust程序员了,一天八小时,几乎完全使用Rust语言编程:用Rust开发标准库(和其他库),用Rust调用标准库开发编译器,用编译器编译标准库和编译器。等到1.0发布时,他们已经是具有多年极其丰富的Rust开发经验的程序员,这期间他们积累的大量设计开发经验和教训,无疑不断地推进了Rust自身的迭代更新。 144 | 145 | 有人说:没有必要自举,不自举不代表它没有这个能力。这话说的没有太大毛病。但是我们考虑如下两点: 146 | 147 | - 1、自举从事实上印证了它(编程语言+编译器)具备这个(强大的)能力,不自举只能在理论上保留它具有这个能力的可能性,两者不在一个层面上,说服力孰强孰弱不言而喻。新语言在大规模推广之前,往往欠缺这种说服力,进而导致推广不利,陷入怪圈不能自拔。 148 | - 2、自举过程中和自举之后,核心开发者每天使用自己开发的语言工作(开发自己的编译器),不断的在实践中锻造,利于及早发现设计缺陷和不足之处,并及时解决;自举之前,只能每天花费大量的时间和精力,使用其他编程语言开发和维护自己的编译器,学习积累的都是别的语言的经验和教训,缺少在实践中检验自己设计的语言的机会。如果自己设计的语言自己都不去深度地使用,又上哪里获取第一手的反馈信息呢,又如何改善呢。 149 | 150 | 所以自举越早对编程语言自身发展完善越有利,最好是在自身定型之前尽早自举。 151 | 152 | 在编程语言自身定型之前尽早自举,这句话说起来容易,实施起来却非常困难。语言不完善,某些功能就可能暂时没法实现;语言不稳定,需要不断的修正和改进,用它写的编译器也需要相应的大量的维护更新甚至重写,是很大的工作负担。所以很多新的编程语言的作者,不愿意(尽早)自举,相应地也就永久失去了自举带来的好处。 153 | 154 | 我(Liigo)举两个反例: 155 | 156 | - 第一个是Google公司的 http://golang.org/[Go语言],截止到2015年本文发表时,其编译器和运行时库,包括语言核心数据结构和算法map、channel、scheduler等等,还是用C语言开发的(Liigo补记:2015年8月1.5版本之后才替换为Go)——他们的核心开发人员真正用自己开发的Go语言进行实际的大型应用开发的机会并不多。虽然标准库是用Go语言自己写的,但他们却没有大范围使用标准库的经历。实际上,他们缺少使用Go语言的实战开发经验,往往不知道处于开发第一线的用户真正需要什么,无法做到设身处地为程序员着想。缺少使用Go语言的亲身经历,也意味着他们不能在日常开发中,及时发现和改进Go语言设计上的缺陷和不足。 157 | - 第二个反例是中文编程的翘楚 —— http://www.eyuyan.com/[易语言],它的编译器、核心支持库、集成开发环境(IDE),和绝大多数支持库,都是用C语言或C+\+语言开发的,他们的主要开发人员,包括创始人吴涛在内,每天的工作是熟练编写大量C/C++代码,写易语言代码的机会少之又少,即使有也是写一些调用支持库的示例这类浅尝辄止的代码。事实上在易语言研发部,只有庄晓立(Liigo)、袁晓辉(海洋)、龚辟愚(GBB)等少数几位开发者具有较深的易语言功底,其他开发人员进入研发部之前甚至都没听过易语言。吴涛本人早年还写过一些较大的易语言程序,代表作是俄罗斯方块(代码多达500行),后期也很少写了,偶尔写一些Sample代码作为支持库的示例(往往不超过100行)。易语言公司里写易语言代码最多的应该是项目教育培训等部的史世恒、潘春华、季翔、王军、张志恒他们。后来易语言暴露出来一些大的设计缺陷,已经不好修复了,除非伤筋动骨地翻修(放弃向后兼容性)。再后来吴涛组织团队又开发了全新的编程语言“易语言.飞扬”(EF),发布之前用EF语言开发了自己的集成开发环境(IDE),是一大进步,但依然没有完成自举。后来听说吴涛自己一个人在搞3D游戏引擎(http://vg3d.cn/[Volcano3D]),气场强大,希望推出真实的游戏(而非demo)检验其优秀品质。 158 | 159 | 而Rust语言,偏偏克服了诸多困难,提前4年完成自举,成为是最成功的案例之一,充分的享受了自举的好处,不断地在实践中完善了自身的设计。 160 | 161 | 没有深度的实践,就没有优秀的设计。除了自举,Rust还有其他的深度实践。 162 | 163 | 164 | == 两个半"大型成功案例": servo, rustc+std, cargo 165 | 166 | (作者Liigo注:本节以下有关代码行数的数据于2015年7月30日得到修正,详情另见 http://blog.csdn.net/liigo/article/details/47103577[关于Servo项目中Rust代码行数的数据来源] 一文。) 167 | 168 | - **Servo**: 下一代浏览器渲染引擎(类Webkit/Blink),超过25万行Rust代码 169 | 170 | Servo是Mozilla公司另外一个独立开发组的项目,启动于2012年初,跟Rust并行开发。多年来,在Rust语言从幼年到少年逐步成长、长期剧烈变动的情况下,Servo居然还能保持正常开发进度,实属不易。Patrick Walton在Servo开发组和Rust开发组都是核心程序员,Servo组的Lars Bergstrom经常参加Rust组的 https://github.com/rust-lang/meeting-minutes/[每周会议],这保证了两部门的有效沟通。Rust组经常会优先协助解决Servo组遇到的问题,维持Servo开发任务正常推进。 171 | 172 | 对于Rust而言,Servo项目存在的最大意义就是,它实践并印证了Rust语言具有实际的大中型项目开发能力(而不仅仅停留在理论上),同时获得了珍贵的设计开发经验和教训,反过来进一步促进了Rust自身的发展。Rust语言和标准库逐步发展到今天,许多优秀的设计得以引进,许多有缺陷的设计得以改良,都要感谢Servo这类大型实践项目,在Rust 1.0之前就已经长期存在。试想,如果Rust定型之后才启动Servo项目,实践中发现语言的重大设计缺陷又能怎样,反正木已成舟,悔之晚矣。 173 | 174 | Servo已经通过了 https://blog.mozilla.org/research/2014/04/17/another-big-milestone-for-servo-acid2/[Acid2] 标准测试;可以 http://blog.servo.org/2015/04/02/twis-29/[并发渲染] Github/Reddit/CNN 这类大型静态网页,性能 http://www.phoronix.com/scan.php?page=news_item&px=MTgzNDA[明显高于] 当前的Firefox浏览器的Gecko引擎;可以无缝替换基于Chrome的 https://github.com/servo/servo/tree/master/ports/cef[CEF] 框架;已经实验性的应用在Firefox OS平台(https://twitter.com/larsberg_/status/539937229049581568[b2s])。2015年将发布测试版浏览器。Servo有机会成为浏览器历史上里程碑式的产品。 175 | 176 | - **rustc+std**: Rust编译器和标准库,超过30万行Rust代码 177 | 178 | 时至今日,rustc负责编译全世界所有的Rust源代码,包括rustc+std的30万行和servo的25万行,以及crates.io网站上的2000多个第三方库,是名副其实的大型成功项目。 179 | 180 | - **Cargo**: Rust的package管理器,项目依赖管理 181 | 182 | 代码量相比前两者而言要小的多,所以我算它是半个成功案例。代码虽少,但实用性、流行度有过之而无不及。全世界大约99%的Rust项目采用Cargo编译。crates.io网站上有2000多个包,总下载量超150万次。Cargo最大幅度地简化了Rust项目的编译和依赖管理,可以说是目前开发Rust项目的必备工具。 183 | 184 | 185 | == 十分重视并认真对待1.0版本 186 | 187 | Rust 1.0被开发者视为第一个稳定可靠的可用于生产环境的正式版本。也就是要承诺:现有的大部分语言特性和标准库API要稳定下来,以后不能轻易改变,非得要变得话也得保持向后兼容;功能上要基本全面,至少要满足基本的软件开发需求,不能有明显的欠缺;质量上要有可靠性保证,不能动不动就这里有问题那里有问题。此外,还要给语言将来的发展留足余地。官方博客 http://blog.rust-lang.org/2014/09/15/Rust-1.0.html[Road to Rust 1.0] 对于 1.0 有详细的阐述。 188 | 189 | 任何认真的新编程语言面临“何时发布1.0版”这个问题时都会感到纠结。发布的越早吧,初级产品没经过多少实际检验,用户量一上来用的人多了,很可能爆出基础设计缺陷,不得已大幅翻修,导致口碑不佳,然后无人问津,项目就算失败了;发布的越晚吧,影响力小用户量一直上不去,也得不到太多实际检验,始终达不到1.0的水平,可能就一直默默无闻下去了。Rust在1.0发布时机上把握的还算比较到位:诞生快十年,高速发展三五年,吸引了一大批用户,自身也经过的“两个半”大型项目的实际检验。要说早,肯定是不早了。Rust没有盲目的早早发布1.0(例如在2012年),是因为他们对1.0期待很高,他们对自己要求很高,他们心里有一杆秤。因为他们是认真的。 190 | 191 | 为了在2015年5月保质保量发布Rust 1.0,他们提前做了哪些工作? 192 | 193 | === 标准库API的稳定性 194 | 195 | Rust为标准库内所有API,即所有fn、所有type(struct/enum/trait)、所有method、所有impl、所有const/static、所有macro_rules!,都逐一标注了稳定性标签:stable、unstable或deprecated。并且声明,1.0版本内包含的所有stable API,都将在SemVer 2.0规范下得到向后兼容性保证,今后所有1.x版本都不会破坏其稳定性(除非遇到重大BUG不得已而为之)。 196 | 197 | 我们去查Rust开发组公开的会议记录,会发现在2014年6月23日到10月1日,共有8次API review专题会议(https://github.com/rust-lang/rust-wiki-backup/blob/master/Meeting-API-review-2014-06-23.md[0] https://github.com/rust-lang/meeting-minutes/blob/master/Meeting-API-review-2014-07-07.md[1] https://github.com/rust-lang/meeting-minutes/blob/master/Meeting-API-review-2014-07-16.md[2] https://github.com/rust-lang/meeting-minutes/blob/master/Meeting-API-review-2014-07-30.md[3] https://github.com/rust-lang/meeting-minutes/blob/master/Meeting-API-review-2014-08-06.md[4] https://github.com/rust-lang/meeting-minutes/blob/master/Meeting-API-review-2014-08-13.md[5] https://github.com/rust-lang/meeting-minutes/blob/master/Meeting-API-review-2014-09-24.md[6] https://github.com/rust-lang/meeting-minutes/blob/master/Meeting-API-review-2014-10-01.md[7]),逐一审查确定各API的稳定性标签。此后更长的时间里,又不定期的将更多API标注为stable或unstable/deprecated,在rust repo里搜索 https://github.com/rust-lang/rust/search?q=stabilize&type=Issues["stabilize"] 可以得到大批提交记录,显示出这项系统工程显然不是一朝一夕所能完成的。 198 | 199 | 目前标准库名下stable API大约有2500条,占总数的80%。新生编程语言中能做到这个程度的,很少见。 200 | 201 | 增补:针对稳定版API的修改,怎样的修改是向后兼容的、怎样的修改是破坏兼容性的呢? https://github.com/rust-lang/rfcs/blob/master/text/1105-api-evolution.md[RFC #1105] 给出了非常详尽的说明和指导。而且Rust还有一个叫Crater的工具,负责检测某项修改是否破坏了兼容性,其工作原理是,借助集成测试环境,以该项修改为基础构建临时Rust工具链,用之逐一编译crates.io网站上的三千多个Rust开源项目,只要有一个不通过,就说明该项修改存在破坏兼容性的可能。许多代码提交后首先要经过Crater的检验才可能被正式接纳(案例: https://github.com/rust-lang/rust/pull/29498[PR #29498] https://github.com/rust-lang/rust/pull/30796[PR #30796] )。 202 | 203 | 增补:Rust在1.0发布之前筹划实施了类似Chrome的滚动式版本升级计划(https://github.com/rust-lang/rfcs/blob/master/text/0507-release-channels.md[RFC #507])。nightly版本6周后升级为beta版本,beta版本6周后升级为stable版本。新提交到创库里的代码,必然经过nightly和beta两个周期,经过总共约12周的测试和过渡期,才会正式进入stable版本。许多核心开发者都是基于nightly版本工作的,还有很有用beta版本的开发者,再加上完善的travis-ci测试,基本可以保证在stable发布之前发现并修正存在的问题,确保stable版本的可靠性。 204 | 205 | === 精益求精的API设计 206 | 207 | - Reform: Collections reform(https://github.com/rust-lang/rfcs/blob/master/text/0235-collections-conventions.md[v1: RFC #235] https://github.com/rust-lang/rfcs/blob/master/text/0509-collections-reform-part-2.md[v2: RFC #509]) https://github.com/rust-lang/rfcs/blob/master/text/0369-num-reform.md[RFC #369: num reform] https://github.com/rust-lang/rfcs/blob/master/text/0439-cmp-ops-reform.md[RFC #439: cmp ops reform] https://github.com/rust-lang/rfcs/blob/master/text/0453-macro-reform.md[RFC #453: macro reform] https://github.com/rust-lang/rfcs/blob/master/text/0474-path-reform.md[RFC #474: path] https://github.com/rust-lang/rfcs/blob/master/text/0517-io-os-reform.md[RFC #517: (big) io os reform (including net fs process env osstr etc.)] https://github.com/rust-lang/rfcs/blob/master/text/1040-duration-reform.md[RFC #1040: Duration reform] 208 | - Revise: https://github.com/rust-lang/rfcs/blob/master/text/0048-traits.md[RFC #48: revised trait matching] https://github.com/rust-lang/rfcs/blob/master/text/0132-ufcs.md[RFC #132: revised UFCS] https://github.com/rust-lang/rust/issues/18469[Issue #18469: revise coercion rules] https://github.com/rust-lang/rust/pull/22435[PR #22435: revise std::thread] https://github.com/rust-lang/rust/pull/11263[PR #11263: revise btree] 209 | - Stabilize: https://github.com/rust-lang/rust/pull/17029[PR #17029: Vec] https://github.com/rust-lang/rust/pull/17438[PR #17438: String] https://github.com/rust-lang/rust/pull/23549[PR #23549: num] https://github.com/rust-lang/rust/pull/22975[PR #22975: ffi] and https://github.com/rust-lang/rust/search?q=stabilize&type=Issues[others] 210 | - Entry API: https://github.com/rust-lang/rfcs/blob/master/text/0921-entry_v3.md[RFC #921: entry v3] (https://github.com/rust-lang/rfcs/pull/216[v1] https://github.com/rust-lang/rfcs/pull/247[v2]) https://github.com/rust-lang/rust/pull/22930[PR #22930] 211 | - String Parterns: https://github.com/rust-lang/rfcs/blob/master/text/0528-string-patterns.md[RFC #528] https://github.com/rust-lang/rust/pull/22466[PR #22466] https://github.com/rust-lang/rust/pull/23952[PR #23952] 212 | - Audit: https://github.com/rust-lang/rust/issues/22820[Issue #22820] https://github.com/rust-lang/rust/pull/24447[PR #24447] https://github.com/rust-lang/rust/pull/22715[PR #22715] https://github.com/rust-lang/rust/search?&q=Audit&type=Issues[others] 213 | - API review: https://github.com/rust-lang/meeting-minutes/blob/master/Meeting-API-review-2014-09-24.md[meeting-2014-09-24] 214 | 215 | 216 | === 精益求精的类型系统设计 217 | 218 | - 改进接口匹配算法: https://github.com/rust-lang/rust/pull/17197 219 | - 新的类型推导机制: https://github.com/rust-lang/rust/pull/15955 220 | - 逐步完善DST系统: https://github.com/rust-lang/rust/issues/12938 221 | - 继续 https://github.com/rust-lang/rust/pull/23867[优化] (https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md[RFC #1023]) https://github.com/rust-lang/rust/pull/20416[orphan rules],确保向前兼容(向未来兼容) 222 | - ... 223 | 224 | === 精益求精的文档和代码复审 225 | 226 | - "Guide: Hello Cargo"经过仔细review: https://github.com/rust-lang/rust/pull/15183[PR #15183] 227 | - "Guide: Strings"经过仔细review: https://github.com/rust-lang/rust/pull/15593[PR #15593] 228 | - "Guide: Pointers"经过仔细review: https://github.com/rust-lang/rust/pull/15789[PR #15789] 229 | - "Guide: macros and unsafe"经过仔细review: https://github.com/rust-lang/rust/pull/16331[PR #16331] 230 | - "A 30-minute Introduction to Rust"经过仔细review: https://github.com/rust-lang/rust/pull/16641[PR #16641] 231 | - "Rust book: guessing game"经过仔细review: https://github.com/rust-lang/rust/pull/25080[PR #25080] 232 | - "Rust book: stack and heap"经过仔细review: https://github.com/rust-lang/rust/pull/25292[PR #25292] 233 | - "Rust book: dining philosophers"经过仔细review: https://github.com/rust-lang/rust/pull/25321[PR #25321] 234 | - "Rust book: concurrency"经过仔细review: https://github.com/rust-lang/rust/pull/21152[PR #21152] 235 | - "cross-compiling for iOS"经过仔细review: https://github.com/rust-lang/rust/pull/14715[PR #14751] 236 | - "regex crate"经过仔细review: https://github.com/rust-lang/rust/pull/13700[PR #13700] 237 | - "flexible target specification"经过仔细review: https://github.com/rust-lang/rust/pull/16156[PR #16156] 238 | - "RingBuf"经过仔细review: https://github.com/rust-lang/rust/pull/18747[PR #18747] https://github.com/rust-lang/rust/pull/19569[PR #19569] 239 | - "HashMap"经过仔细review: https://github.com/rust-lang/rust/pull/16628[PR #16628] https://github.com/rust-lang/rust/pull/19946[PR #19946] 240 | - "Rustdoc: sidebar tooltips"经过仔细review: https://github.com/rust-lang/rust/pull/20221[PR #20021] 241 | - "Rewrite associated types"经过仔细review: https://github.com/rust-lang/rust/pull/20307[PR #20307] 242 | - "new std::path"经过仔细review: https://github.com/rust-lang/rust/pull/21759[PR #21759] 243 | - "String patterns"经过仔细review: https://github.com/rust-lang/rust/pull/22466[PR #22466] 244 | - "primitives inherent methods"经过仔细review: https://github.com/rust-lang/rust/pull/23104[PR #23104] 245 | - "floating-to-decimal formatting"经过仔细review: https://github.com/rust-lang/rust/pull/24612[PR #24612] 246 | - "Vec::drain"经过仔细review: https://github.com/rust-lang/rust/pull/24781[PR #24781] 247 | - "Redesign Duration"经过仔细review: https://github.com/rust-lang/rust/pull/24920[PR #24920] 248 | 249 | === 1.0之后的开发计划 250 | 251 | 1.0是起点而不是终点,1.0之后Rust还将持续不断地开发新的语言特性,打造更完善的标准库。 252 | 253 | 核心开发者Niko Matsakis在今年4月份发表 http://internals.rust-lang.org/t/priorities-after-1-0/1901[Priorities after 1.0] 一文,详细阐述了1.0之后的开发任务、计划、优先级,内容很多却安排有序,体现了他们对这些问题的深度思考。此文在开发者社区中引起强烈反响,获得热烈讨论。Niko还发表了系列博客文章的第一篇 http://smallcultfollowing.com/babysteps/blog/2015/05/05/where-rusts-enum-shines/["Virtual Structs Part 1: Where Rust’s Enum Shines"]。 254 | 255 | 256 | 257 | == 精心设计的规范透明的开发流程 258 | 259 | 在2014年3月之前,Rust开发组并没有十分规范的开发流程,基本过程是这样:修改代码,提交PR,Review,Merger。这样导致的问题是,没有形成设计文档,一旦遇到较大规模的代码改动,别人想理解他的设计思路,首先要读懂他的代码,这给方案评估、代码评审制造了困难,而且容易形成无人理解或难于维护的代码。 260 | 261 | 从2014年3月开始,Rust引入了规范化的RFC流程。规定,对语言重大改动之前,需先提交RFC文档,写明包括意图、详细设计、优缺点等在内的完整技术方案,供社区集体讨论,最后提交到Rust核心开发组每周的专题会议上评估审核,获得批准之后才进入实施阶段(代码实现)。规范化RFC的好处是,首先形成了完整的技术文档,利于集体讨论、评估(进而优化方案),利于方案实施、后期维护,而且利于核心开发组主导项目进展方向。RFC流程实施一年来,在Rust发展过程中发挥了极其深远的作用,先后通过了一大批十分重要的RFC,有力地推动了Rust语言的革新。 262 | 263 | - 6个继承RFC: https://github.com/rust-lang/rfcs/pull/5[PR #5] https://github.com/rust-lang/rfcs/pull/9[PR #9] https://github.com/rust-lang/rfcs/pull/11[PR #11] https://github.com/rust-lang/rfcs/pull/142[PR #142] https://github.com/rust-lang/rfcs/pull/223[PR #223] https://github.com/rust-lang/meeting-minutes/blob/master/weekly-meetings/2014-09-09.md#inheritance[...] 这些都是提案,暂时没有胜出者,所以都没有RFC编号。1.0之后将决出谁是最佳可行方案。 264 | - associated items: https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md[RFC #195] 265 | - io os reform: https://github.com/rust-lang/rfcs/blob/master/text/0517-io-os-reform.md[RFC #517] 266 | - collections reform: https://github.com/rust-lang/rfcs/blob/master/text/0235-collections-conventions.md[v1: RFC #235] https://github.com/rust-lang/rfcs/blob/master/text/0509-collections-reform-part-2.md[v2: RFC #509] 267 | - Scaling Rust's Governance: https://github.com/rust-lang/rfcs/blob/master/text/1068-rust-governance.md[RFC #1068] 268 | 269 | 举一个例子,说明社区会主动监督开发流程的规范性和透明度:2014年8月,官方人员aturon居然想偷偷摸摸地把unwrap方法改名为assert, https://github.com/rust-lang/rust/pull/16436[PR #16436: API conventions cleanup](80+),被网友 http://www.reddit.com/r/rust/comments/2dbg3j/hm_unwrap_is_being_renamed_to_assert/[发现](120+) 后引起极大争议。争议的起因是他们工作透明度不够,事先 https://internals.rust-lang.org/t/settling-some-key-naming-conventions/269[公示](50+) 范围不足,未得到充分讨论。最终这一改动被迫撤消。 270 | 271 | 272 | 增补:1.0发布前后筹备创建了Sub Teams,整合了各细分领域的开发专家,负责所属领域的RFC设计、讨论、评估、决策,令过程更专业化。之前的Core Team,只有少数几位官方核心开发人员,地位相当于我党的政治局常委会,技术、能力、威望都很牛逼,但随着开发规模的扩大,他们自己也忙的团团转,疲于参与呈爆发式增长的RFC,工作效率不高,况且他们未必在所有细分领域都是专家,一把抓并不理想。组建Language Design Team, Library Team, Compiler Team, Tooling and Infrastructure Team, Community Team, Moderation Team 等 Sub Teams之后,各自吸纳了来自官方和民间的细分领域专家,可以更加专业化更有针对性的处理本领域的RFC,同时给Core Team节省出宝贵的精力去处理更核心的工作(Sub Teams有时上报某些重要RFC给Core Team决策)。参见 https://github.com/rust-lang/rfcs/blob/master/text/1068-rust-governance.md[RFC #1068]。 273 | 274 | 增补:1.0发布后对每周技术例会(https://github.com/rust-lang/meeting-minutes[meetimg-minutes])做了较大调整。之前的惯例是,民间开发人员在RFC页面上讨论,然后Core Team开发人员在每周例会上讨论并决策,最后公布会议记录。之后的惯例是,民间和官方人员一起在RFC页面讨论,然后Sub team闭门决策(必要时Core Team介入),最后公布决策结果。调整之后,讨论更民主化、透明化,决策更集中化,提升了工作效率。 275 | 276 | 增补:(2014年那时候,北京时间每周三凌晨Core Team发布会议记录,每周三就是我(Liigo)的节日,早上起床看Core Team的技术讨论和决策过程,持续了大约一年,现在还是美好的回忆。后来Sub Teams的会议记录通常只剩下决策结果,没有技术讨论过程了,而且他们的发布间隔也延长到两周左右。) 277 | 278 | 增补:1.0发布后为RFC增设了 “Final Comment Period (FCP)” 窗口期,并及时公告,使得关注该RFC的开发者不会轻易错过决策前的最后集中讨论阶段。这也是提供开发透明度的一项措施。同样参见 https://github.com/rust-lang/rfcs/blob/master/text/1068-rust-governance.md[RFC #1068]。 279 | 280 | 281 | == 不拘一格聘请专业技术人员 282 | 283 | Steve Klabnik之前写过一篇介绍Rust的入门教程 http://www.rustforrubyists.com/book/book.html[Rust for Rubyists],文风娓娓道来,深得群众喜爱。2014年2月,Rust官方人员看重了他的文档写作才华,付费 https://github.com/rust-lang/rust/issues/9874#issuecomment-35457593[聘请] 他全职为Rust http://www.reddit.com/r/rust/comments/28bew8/rusts_documentation_is_about_to_drastically/[创作文档]。他的主要代表作是Rust官方的 http://doc.rust-lang.org/book/[The Rust Programming Language](Rust Book),以及大量API Docs。因为其卓越贡献,steveklabnik目前已经 http://blog.rust-lang.org/2014/12/12/Core-Team.html[成为] http://www.rust-lang.org/team.html[Rust核心开发组] 八成员之一。 284 | 285 | Tilde公司以前开发的Ruby包管理器Bundler在Ruby领域非常流行,其架构设计被实践证实获得成功。2014年3月,Rust官方 https://mail.mozilla.org/pipermail/rust-dev/2014-March/009087.html[宣布] http://www.reddit.com/r/rust/comments/20okr4/rustdev_announcing_the_new_rust_package_manager/[聘请] Tilde公司的核心技术人员Yehuda Katz和Carl Lerche,全职为Rust设计开发全新的开源的 https://github.com/rust-lang/cargo[Cargo],目标是打造世界级的包管理器("a world-class package manager for Rust")。现在Cargo已经初步获得了很大的成功,还在蓬勃发展中。因为Yehuda Katz的卓越贡献,他已经 http://blog.rust-lang.org/2014/12/12/Core-Team.html[成为] http://www.rust-lang.org/team.html[Rust核心开发组] 八成员之一。 286 | 287 | 深受好评的Rust学习示例网站 http://rustbyexample.com 的早期创建者 Jorge Aparicio(japaric) 后来被邀请 https://github.com/rust-lang/meeting-minutes/blob/master/weekly-meetings/2014-09-02.md#friend-of-the-tree[加入] 了(Mozilla公司的)Rust官方团队。 288 | 289 | 去 https://github.com/rust-lang/meeting-minutes[meeting-minutes] 里面搜索 "Friend of the Tree" 或 "fott" 你会发现更多人陆续加入了Rust开发团队。 290 | 291 | 292 | == 大规模的广泛的社区参与 293 | 294 | 社区用Rust开发的或与Rust相关的开源项目进展地风风火火: https://github.com/servo/servo[Servo], https://github.com/rust-lang/cargo[Cargo], https://github.com/rust-lang/rust-by-example[rust-by-example], https://github.com/hyperium/hyper[Hyper], https://github.com/PistonDevelopers/piston[Piston], https://github.com/uutils/coreutils[coreutils], https://github.com/sfackler/rust-postgres[rust-postgres], https://github.com/gfx-rs/gfx-rs[gfx-rs], https://github.com/PistonDevelopers/conrod[conrod], https://github.com/AngryLawyer/rust-sdl2[rust-sdl2], https://github.com/DaGenix/rust-crypto[rust-crypto], https://github.com/docopt/docopt.rs[docopt.rs], https://github.com/hackndev/zinc[zinc], https://github.com/bjz/gl-rs[gl-rs], https://github.com/phildawes/racer[racer], https://github.com/crabtw/rust-bindgen[rust-bindgen], https://github.com/bjz/glfw-rs[glfw-rs], https://github.com/dwrensha/capnproto-rust[capnproto-rust], https://github.com/Hoverbear/rust-rosetta[rust-rosetta], https://github.com/PistonDevelopers/graphics[graphics], https://github.com/sfackler/rust-openssl[rust-openssl], https://github.com/lifthrasiir/rust-encoding[rust-encoding], https://github.com/PistonDevelopers/hematite[hematite], https://github.com/dwrensha/capnproto-rust[capnproto-rust], https://github.com/tomaka/glium[glium], https://github.com/servo/html5ever[html5ever], https://github.com/tomaka/glutin[glutin], https://github.com/servo/rust-layers[rust-layers], https://github.com/erickt/rust-serde[rust-serde] …… 295 | 296 | 我上面列出的多是长期以来持续开发和维护的项目,这在Rust语言长期剧烈变动的情况下愈显弥足珍贵。理智的人们不会无缘无故的花费大量时间和精力。许多忠实的第三方开发者长期地投资Rust项目,体现了他们对于Rust语言的热爱和对其前景的看好。 297 | 298 | === 社区合力完成的项目(libextra, diagnostics): 299 | 300 | ==== 分解extra库 https://github.com/rust-lang/rust/issues/8784[Issue #8784]: 301 | 302 | - https://github.com/mozilla/rust/pull/11787 (flate) 303 | - https://github.com/mozilla/rust/pull/11867 (arena glob) 304 | - https://github.com/mozilla/rust/pull/11912 (uuid) 305 | - https://github.com/mozilla/rust/pull/11939 (sync) 306 | - https://github.com/mozilla/rust/pull/11945 (term) 307 | - https://github.com/mozilla/rust/pull/11984 (serialize) 308 | - https://github.com/mozilla/rust/pull/12007 (getopts) 309 | - https://github.com/mozilla/rust/pull/12010 (collections) 310 | - https://github.com/mozilla/rust/pull/12012 (semver) 311 | - https://github.com/mozilla/rust/pull/12154 (num) 312 | - https://github.com/rust-lang/rust/pull/12200 (base64 hex) 313 | - https://github.com/rust-lang/rust/pull/12343 (test) 314 | - ... 315 | 316 | ==== 详解编译错误 https://github.com/rust-lang/rust/issues/24407[Issue #24407]: 317 | 318 | - https://github.com/rust-lang/rust/pull/24431 (E0297, E0301, E0302, E0162, E0165) 319 | - https://github.com/rust-lang/rust/pull/24455 (E0152, E0158, E0161, E0170, E0306, E0307) 320 | - https://github.com/rust-lang/rust/pull/24482 (E0009) 321 | - https://github.com/rust-lang/rust/pull/24488 (E0015, E0020) 322 | - https://github.com/rust-lang/rust/pull/24525 (E0018) 323 | - https://github.com/rust-lang/rust/pull/24552 (E0133) 324 | - https://github.com/rust-lang/rust/pull/24728 (E0271) 325 | - https://github.com/rust-lang/rust/pull/24966 (E0282) 326 | - https://github.com/rust-lang/rust/pull/24975 (E0079, E0080, E0081, E0082, E0083, E0084) 327 | - https://github.com/rust-lang/rust/pull/25190 (E0046, E0054) 328 | - https://github.com/rust-lang/rust/pull/25200 (E0062, E0063, E0137) 329 | - https://github.com/rust-lang/rust/pull/25272 (E0184, E0204, E0205, E0206, E0243, E0244, E0249, E0250) 330 | - https://github.com/rust-lang/rust/pull/25398 (E0053, E0066, E0069, E0251, E0252, E0255, E0256, E0368) 331 | - https://github.com/rust-lang/rust/pull/25422 (E0197, E0198, E0199, E0200) 332 | - ... 333 | 334 | ==== 排错语言手册 https://github.com/rust-lang/rust/issues/16676[Issue #16676] 335 | 336 | === 社区广泛参与的大型技术讨论: 337 | 338 | ==== inherents: 339 | 340 | 围绕实现“继承”这一语言特性,社区涌现出一批设计方案,一时间争奇斗艳。暂时没有结果,最终决策要在1.0之后才能做出。(括号内是评论数,下同。) 341 | 342 | - https://github.com/rust-lang/rfcs/pull/5[RFC PR #5: Virtual structs](10+) 343 | - https://github.com/rust-lang/rfcs/pull/9[RFC PR #9: Fat objects](20+) 344 | - https://github.com/rust-lang/rfcs/pull/11[RFC PR #11: Extending enums](10+) 345 | - https://github.com/rust-lang/rfcs/pull/142[RFC PR #142: Efficient single inheritance](60+) 346 | - https://github.com/rust-lang/rfcs/pull/223[RFC PR #223: Trait based inheritance](40+) 347 | - https://internals.rust-lang.org/t/summary-of-efficient-inheritance-rfcs/494[Summary](40+) 348 | - inheritance meeting https://github.com/rust-lang/meeting-minutes/blob/d1710f1799e053d5dad99be2d4ee666567056b4e/Meeting-inheritance-2014-09-23.md[2014-09-23] https://github.com/rust-lang/meeting-minutes/blob/99afa26ad073ab42d174c7f4ebd516513062f072/Meeting-inheritance-2014-09-30.md[2014-09-30] 349 | 350 | ==== scoped thread: 351 | 352 | 2015年4月11日爆出这个大BUG(https://github.com/rust-lang/rust/issues/24292[Issue #24292]),直接拷问Rust“内存安全”核心概念,当时距离1.0发布已不足5周时间。要知道,刚刚一天前,`std::thread::scoped()`还被 http://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html[官博] 当作既安全又典雅的优秀API的典型、满怀骄傲地向全世界推介。是不幸,还是该庆幸?我认为该庆幸,有机会消除一个隐患,而不是在不知情中带着重大缺陷进入1.0。 353 | 354 | - https://github.com/rust-lang/rust/issues/24292[Issue #24292: std::thread::JoinGuard (and scoped) are unsound because of reference cycles](30+) 355 | - https://github.com/rust-lang/rfcs/pull/1066[RFC #1066: Alter mem::forget to be safe](270+) 356 | - https://github.com/rust-lang/rfcs/pull/1084[RFC PR #1084: Scoped threads, take 2](90+) 357 | - https://github.com/rust-lang/rfcs/pull/1085[RFC PR #1085: Leak and Destructor Guarantees](70+) 358 | - https://github.com/rust-lang/rfcs/pull/1094[RFC PR #1094: Guaranteed non-static destructors](70+) 359 | - http://www.reddit.com/r/rust/comments/3404ml/prepooping_your_pants_with_rust/[Pre-Pooping Your Pants With Rust](100+) 360 | - http://www.reddit.com/r/rust/comments/34bj7z/on_referencecounting_and_leaks_from_nmatsakiss/[On reference-counting and leaks](110+) and http://smallcultfollowing.com/babysteps/blog/2015/04/30/a-few-more-remarks-on-reference-counting-and-leaks/[a few more] 361 | 362 | 官方人员一味的强调 Issue #24292 是个例,一味的强调“不保证析构函数务必执行”不违反内存安全,并不能消除群众心中的不安全感。在我看来,官方人员给出的解决方案(RFC PR #1066 #1084)一个是“头痛医头”一个是“脚痛医脚”,反而是民间技术人员提交的方案(RFC PR #1085 #1094)更接地气,至少是朝群众期望的方向努力了。可能是1.0发布日期逼近,实在没有时间评估和实施其他方案,最终官方坚持通过了RFC #1066。这一次我给他们集体评负分。好在他们广泛深入地参与了所有相关的讨论,内部无争议地做出了理性决策,结果未必坏。 363 | 364 | ==== mutable & unique: 365 | 366 | Rust社区对于可变性(mutable)和唯一性(unique)的反思和争议。所有这些话题,都引发了许多热烈的讨论和激烈的争论,火热程度空前。之前 reddit.com/r/rust 内评论数达到200+的极为少见。 367 | 368 | - 先是RFC 58,DaGenix 要求把 &mut 改为 https://github.com/rust-lang/rfcs/pull/58[&only](50+) 369 | - 再是 Nicholas 要求彻底取消mut,增加 http://www.reddit.com/r/rust/comments/25i544/babysteps_focusing_on_ownership_or_removing_let/[unique](240+) 引用 370 | - 还有pcwalton发出的 http://www.reddit.com/r/rust/comments/2581s5/[追问](180+):谁表达更清晰,可变性(mutability)还是唯一性(uniqueness)? 371 | 372 | ==== others 373 | 374 | - int/uint => isize/usize: 375 | - integer overflow: 376 | - reddit/HN hot posts: 377 | - Rust中文社区(http://rust.cc/[rust.cc]),新手QQ群(http://qm.qq.com/cgi-bin/qm/qr?k=7JPj8RKFpxCj2tmZ68r8141R2ev5dLJK[303838735]) 378 | 379 | 大量的、广泛的、深入的社区技术讨论,体现了人民群众积极参与Rust开源项目的热情。多个体、多角度、多出发点的争论,有利于参与者充分认清同一个技术问题,有利于鉴别各方案的优缺点,有利于折中优选最佳可行方案。优质社区是Rust发展的基石。 380 | 381 | 当多方争论不相上下的时候,我们发现,Rust拥有一个坚强的核心团队(http://www.rust-lang.org/team.html[the core team]),总是会应急出面,充当主心骨,做出最终的理性决策,避免出现互相扯皮却始终一事无成的最坏结局。他们的实力是有目共睹的,他们的信誉是逐步赢得的,他们做出的选择,不一定是最优的,但一定也不差。 382 | 383 | 384 | 385 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 386 | ____ 387 | 全文完,感谢!(翻页到这里也不容易呀,顺便吐个槽吧:)~ 388 | ____ 389 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 390 | -------------------------------------------------------------------------------- /learn-rust-2024.md: -------------------------------------------------------------------------------- 1 | 初步掌握RUST基础应用开发 2 | 庄晓立,2024年3月。 3 | 4 | ---- 5 | 6 | # Rust简介 7 | 8 | > A language empowering everyone to build reliable and efficient software. 9 | 10 | Rust编程语言赋能所有人开发高可靠且高性能的软件。 11 | 12 | ## 性能 13 | 14 | > Rust is blazingly fast and memory-efficient: with no runtime or garbage collector, it can power performance-critical services, run on embedded devices, and easily integrate with other languages. 15 | 16 | Rust能够编译出高性能运行且低内存占用的软件,没有运行时或垃圾收集器,适用于高性能服务、嵌入式设备,方便与其他语言集成。 17 | 18 | ## 可靠 19 | 20 | > Rust’s rich type system and ownership model guarantee memory-safety and thread-safety — enabling you to eliminate many classes of bugs at compile-time. 21 | 22 | Rust拥有丰富的类型系统、所有者模型,保证内存安全和线程安全,让你在编译时消除许多类型的BUG。 23 | 24 | ## 开发效率 25 | 26 | > Rust has great documentation, a friendly compiler with useful error messages, and top-notch tooling — an integrated package manager and build tool, smart multi-editor support with auto-completion and type inspections, an auto-formatter, and more. 27 | 28 | Rust有完善的文档,有友好的编译器输出实用的错误信息,有一流的工具:集成包管理器和编译工具,有多种编辑器且支持自动完成和类型审视,有代码格式化工具,等等。 29 | 30 | # 安装Rust 31 | 32 | 推荐使用rustup安装Rust。 33 | 34 | 首先访问网站 https://rustup.rs/ ,下载 rustup-init.exe,然后按照提示逐步操作,即可完成安装Rust。 35 | 36 | 注意:在Windows操作系统下Rust需要依赖MSVC Build Tools(另有其他版本依赖gcc或clang)。 37 | 38 | MSVC Build Tools可以在MS Visual Studio安装包内选装,确保选中模块“使用C++的桌面开发”(英文版“Desktop development With C++”)即可。 39 | 40 | 建议先安装MSVC Build Tools,然后再运行 rustup-init.exe 安装Rust,以便Rust自动找到MSVC链接器link.exe。 41 | 42 | # 配置Rust开发和调试环境 43 | 44 | 针对VS Code编辑器,推荐使用两个插件:rust-analyzer,CodeLLDB。前者用于语法高亮和代码提示,后者用于调试。 45 | 46 | 安装方法:在VS Code的extensions界面搜索插件名称,点击install按钮即可。 47 | 48 | # Rust基础开发知识 49 | 50 | ## Hello world 51 | 52 | 源文件hi.rs: 53 | ```rust 54 | fn main() { 55 | println!("Hello world!"); 56 | } 57 | ``` 58 | 59 | 编译:`rustc hi.rs` 60 | 61 | 运行:`./hi` 62 | 63 | ## Playground 64 | 65 | The Rust Playground, https://play.rust-lang.org/ , 用于在线编译和运行测试代码。 66 | 67 | 68 | ## 输出 69 | 70 | 宏 [`println!`](https://doc.rust-lang.org/nightly/std/macro.println.html) 用于向stdout输出文本并换行。其首参数为格式文本(format string),其中`{}`和`{var}`作为占位符。 71 | ```rust 72 | let name = "liigo"; 73 | println!("hello {name}"); // 输出:hello liigo 74 | let a = 123; 75 | let b = "str"; 76 | println!("a={a} b={b}"); // 输出:a=123 b=str 77 | println!("a={} b={}", a, b); // 同上 78 | ``` 79 | 80 | ## 注释 81 | 82 | ```rust 83 | // 单行注释 84 | 代码 // 行尾注释 85 | 86 | /* 87 | 多行注释 88 | 多行注释 89 | */ 90 | 代码 /* 行中或跨行注释 */ 代码 91 | 92 | /// 外置文档注释(用于生成API文档),首行用一句话简要介绍。 93 | /// 94 | /// 空一行后,详细说明其功能、参数、返回值、示例代码、Unsafe、Panic等。 95 | /// 注释位于被注释的项目上方 96 | 97 | //! 内置文档注释(用于生成API文档),首行用一句话简要介绍。 98 | //! 99 | //! 空一行后,是详细说明。 100 | //!这类文档注释主要用在模块源文件首部,把文档和代码放在一个文件内,方便维护。 101 | ``` 102 | 103 | 下述两处位置的文档注释是等效的(区别仅位置不同,outer-doc-comments VS inner-doc-comments) 104 | 105 | ```rust 106 | /// 外置 107 | mod x { 108 | //! 内置 109 | } 110 | ``` 111 | 112 | 需要内置文档注释的场景,通常是文件模块顶部文档和根模块顶部文档,参见下文。 113 | 114 | ## 程序结构 115 | 116 | Rust程序源码由一个或多个源文件(.rs)组成,但只有一个根源文件(通常命名`main.rs`或`lib.rs`)。 117 | 118 | 编译时只需给编译器(rustc)传入根源文件(无需传入其他源文件),编译器根据源码内部模块结构自动识别并载入其他源文件。 119 | 120 | 假设 main.rs 内有代码`mod web;`,当你使用命令行`rustc main.rs`编译时,编译器会尝试在如下位置寻找web模块的源文件: 121 | - `#[path = "..."]` 指定的目录和/或源文件(如果有的话) 122 | - web.rs 123 | - web/mod.rs 124 | 125 | `main.rs`或`lib.rs`默认定义了根模块,其内部的`mod web;`定义了子模块web。子模块也可以有子模块,共同组成模块树,此模块树上每一个模块(包括根模块)内部都可以定义类型、函数等Items。 126 | 127 | 模块树定义了程序内部抽象结构,源文件树也能较好的体现模块结构。二者还可以灵活结合,实现定制的目录结构(主要依靠`#[path = "..."]`)和模块结构(主要依靠`pub use`)。 128 | 129 | ## 定义模块 130 | 131 | 方式1:内联模块 132 | ```rust 133 | 134 | /// 文档 135 | mod mod1 { 136 | // 代码 137 | } 138 | 139 | ``` 140 | 141 | 方式2:文件模块 142 | 143 | 源文件main.rs: 144 | ```rust 145 | mod mod2; 146 | ``` 147 | 148 | 源文件mod2.rs: 149 | ```rust 150 | //! 文档 151 | 152 | // 代码 153 | ``` 154 | 155 | 以上定义的mod1和mod2均为当前模块的子模块。 156 | 157 | ## 数据类型 158 | 159 | 基础数据类型: 160 | 161 | - 逻辑/字符/文本:bool, char, str 162 | - 有符号整数:i8, i16, i32, i64, i128 163 | - 无符号整数:u8, u16, u32, u64, u128 164 | - 浮点数:f32, f64 165 | - Never: ! 166 | 167 | 其他数据类型: 168 | 169 | - 序列相关:Tuple, Array, Slice 170 | - 自定义相关:Struct, Enum, Union 171 | - 函数相关:Functions, Closures 172 | - 指针相关:References, Raw pointers, Function pointers 173 | - 接口相关:Trait objects, Impl trait 174 | 175 | 参考:https://doc.rust-lang.org/stable/reference/types.html 176 | 177 | ## 定义变量 178 | 179 | ```rust 180 | let a = 123; 181 | let b = 123i8; 182 | let c: i32 = 123; 183 | let d = Some(123); // d: Option 184 | let Some(x) = Some(123); // x: i32 185 | let mut y = 0; // mut变量 186 | y = 123; // 仅mut变量可以被赋值或被改变 187 | ``` 188 | 189 | ## 定义类型 190 | 191 | ```rust 192 | struct Counter { 193 | n: i32, 194 | } 195 | 196 | impl Counter { 197 | pub fn new() -> Counter { 198 | Counter { 199 | n: 0, 200 | } 201 | } 202 | 203 | pub fn get(&self) -> i32 { 204 | self.n 205 | } 206 | 207 | pub fn add(&mut self, x: i32) { 208 | self.n += x; 209 | } 210 | } 211 | 212 | #[test] 213 | fn test1() { 214 | let mut counter = Counter::new(); 215 | assert_eq!(counter.get(), 0); 216 | counter.add(1); 217 | assert_eq!(counter.get(), 1); 218 | counter.add(-2); 219 | assert_eq!(counter.get(), -1); 220 | } 221 | ``` 222 | 223 | ## 定义和实现接口 224 | 225 | ```rust 226 | trait Inc { 227 | fn inc(&mut self); 228 | } 229 | 230 | impl Inc for Counter { 231 | fn inc(&mut self) { 232 | self.add(1); 233 | } 234 | } 235 | 236 | impl Clone for Counter { 237 | fn clone(&self) -> Self { 238 | Counter { 239 | n: self.get(), 240 | } 241 | } 242 | } 243 | 244 | #[test] 245 | fn test2() { 246 | let mut counter = Counter::new(); 247 | counter.inc(); 248 | counter.inc(); 249 | let counter2 = counter.clone(); 250 | assert_eq!(counter2.get(), 2); 251 | } 252 | ``` 253 | 254 | ## 流程控制 255 | 256 | ```rust 257 | let a = 1; 258 | if a == 1 { 259 | println!("a == 1"); 260 | } else { 261 | println!("a = {a}"); 262 | } 263 | 264 | enum Kinds { K1, K2, K3 } 265 | let kind = Kinds::K1; 266 | match kind { 267 | Kinds::K1 => { println!("K1"); } 268 | Kinds::K2 => { println!("K2"); } 269 | Kinds::K3 => { println!("K3"); } 270 | } 271 | 272 | let nums = [1, 2, 3, 4, 5, 6, 7]; 273 | for n in nums { 274 | print!("{n} "); 275 | } 276 | 277 | while cond { 278 | // code 279 | } 280 | 281 | loop { 282 | // code 283 | if cond { 284 | break; 285 | } 286 | } 287 | ``` 288 | 289 | ## 使用标准库 290 | 291 | Rust程序默认静态链接标准库std,里面包含了很多常用模块/类型/接口/函数,可按需使用。 292 | 293 | 标准库在线文档:https://doc.rust-lang.org/stable/std/index.html 294 | 295 | ```rust 296 | use std::fs::File; 297 | use std::io::{BufRead, BufReader}; 298 | 299 | fn main() { 300 | let file = File::open("./2023-09-15.log").unwrap(); 301 | for line in BufReader::new(file).lines() { 302 | println!("{}", line.unwrap()); 303 | } 304 | } 305 | ``` 306 | 307 | ## 使用Cargo和第三方库 308 | 309 | 使用Cargo创建项目:`cargo init my_project` (生成项目目录,含`Cargo.toml` `src\main.rs`等) 310 | 311 | 使用Cargo编译项目:`cargo build` (在项目目录内执行,下同) 312 | 313 | 使用Cargo运行项目:`cargo run` 314 | 315 | 添加第三方库依赖项:`cargo add chrono` (参见 [chrono](https://crates.io/crates/chrono) [docs](https://docs.rs/chrono)) 316 | 317 | src\main.rs: 318 | ```rust 319 | use chrono::Local; 320 | 321 | fn main() { 322 | println!("Hello, world! {}", Local::now()); 323 | } 324 | ``` 325 | 326 | Cargo.toml: 327 | ```toml 328 | [package] 329 | name = "my_project" 330 | version = "0.1.0" 331 | edition = "2021" 332 | 333 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 334 | 335 | [dependencies] 336 | chrono = "0.4.35" 337 | ``` 338 | 339 | 其中最后一行是执行`cargo add chrono`时自动写入的。 340 | 341 | ## 测试 342 | 343 | 用`#[cfg(test)] mod tests`定义测试模块,用`#[test] fn`定义测试函数,用`cargo test`启动测试。 344 | 345 | ```rust 346 | pub fn add(left: usize, right: usize) -> usize { 347 | left + right 348 | } 349 | 350 | #[cfg(test)] 351 | mod tests { 352 | use super::*; 353 | 354 | #[test] 355 | fn it_works() { 356 | let result = add(2, 2); 357 | assert_eq!(result, 4); 358 | } 359 | } 360 | ``` 361 | 362 | ## 坑 363 | 364 | ```rust 365 | fn do_something() -> std::io::Result<()> { 366 | std::fs::File::open("./nosuchfile")?; // 因为某个错误提前返回 367 | println!("the main work"); 368 | Ok(()) 369 | } 370 | 371 | fn main() { 372 | // 此处故意无视do_something()返回值,后果很严重: 373 | // 程序无故中途退出,无错误信息输出,也没法看调用栈,难以定位问题所在。 374 | // 正确的写法是`do_something().unwrap();`,`do_something().expect("...");`,或`do_something()?;` 375 | let _r = do_something(); 376 | 377 | // 另一种无视返回值的写法是:`do_something().ok();` 378 | // 现实中一定要杜绝这类错误写法,因为后果真的很严重。 379 | 380 | // 为什么程序中途退出:因为代码控制流程提前返回了(?运算符具有提前返回的语义) 381 | // 为什么没有错误输出和调用栈:因为没有执行到panic!(unwrap/expect内部执行到panic!才会有相关输出) 382 | } 383 | ``` 384 | --------------------------------------------------------------------------------