对 C 的漫长的告别
==========================================


这几天来，我就在思考那些能够挑战 C 语言作为系统编程语言堆中的根节点的地位的新潮语言，尤其是 Go 和 Rust。我发现了一个让我震惊的事实 —— 我有着 35 年的 C 语言经验。每周我都要写很多 C 代码，但是我已经忘了我上一次是在什么时候 _创建新的 C 语言项目_ 了。

如果你认为这件事情不够震惊，那你可能不是一个系统程序员。我知道有很多程序员使用更高级的语言工作。但是我把大部分时间都花在了深入打磨像 NTPsec ， GPSD 以及 giflib 这些东西上。熟练使用 C 语言在这几十年里一直就是我的专长。但是，现在我不仅是不再使用 C 语言写新的项目，而且我都记不清我什么时候开始这样做的了。而且...回望历史，我不认为这是本世纪发生的事情。

当你问到我我的五个核心软件开发技能，“C 语言专家” 一定是你最有可能听到的，这件事情对我来说很好。这也激起了我的思考。C 的未来会怎样 ？C 是否正像当年的 COBOL 一样，在辉煌之后，走向落幕？

我恰好是在 C 语言迅猛发展并把汇编语言以及其他许多编译型语言挤出主流存在的前几年开始编程的。那场过渡大约是在 1982 到 1985 年之间。在那之前，有很多编译型语言来争相吸引程序员的注意力，那些语言中还没有明确的领导者；但是在那之后，小众的语言直接毫无声息的退出舞台。主流的（FORTRAN,Pascal，COBOL）语言则要么只限于老代码，要么就是固守单一领域，再就是在 C 语言的边缘领域顶着愈来愈大的压力苟延残喘。

在那以后，这种情形持续了近 30 年。尽管在应用程序开发上出现了新的动向： Java, Perl, Python, 以及许许多多不是很成功的竞争者。起初我很少关注这些语言，这很大一部是是因为在它们的运行时的开销对于当时的实际硬件来说太大。因此，这就使得 C 的成功无可撼动；为了使用之前存在的 C 语言代码，你得使用 C 语言写新代码（一部分脚本语言尝试过大伯这个限制，但是只有 Python 做到了）

回想起来，我在 1997 年使用脚本语言写应用时本应该注意到这些语言的更重要的意义的。当时我写的是一个帮助图书管理员使用一款叫做 SunSITE 的源码分发式软件，我使用的那个语言，叫做 Perl。

这个应用完全是基于文本的，而且只需要以人类能反应过来的速度运行（大概 0.1 秒），因此使用 C 或者别的没有动态内存分配以及字符串类型的语言来写就会显得很傻。但是在当时，我仅仅是把其视为一个试验，我在那时没想到我几乎再也不会在一个新项目的第一个文件里敲下  “int main(int argc, char **argv)” 了。

我说“几乎”，主要是因为 1999 年的 [SNG][3].我像那是我最后一个从头开始写的项目。在那之后我的所有新的 C 代码都是为我贡献代码，或者成为维护者的项目而写 —— 比如 GPSD 以及 NTPsec。

当年我本不应该使用 C 语言写 SNG 的。因为在那个年代，摩尔定律的快速循环使得硬件愈加便宜，像 Perl 这样的语言的运行也不再是问题。仅仅三年以后，我可能就会毫不犹豫地使用 Python 而不是 C 语言来写 SNG。

在 1997 年学习了 Python 这件事对我来说是一道分水岭。这个语言很完美 —— 就像我早年使用的 Lisp 一样，而且 Python 还有很酷的库！还完全绑定了 POSIX！还有一个绝不完犊子的对象系统！Python 没有把 C 语言挤出我的工具箱，但是我很快就习惯了在只要能用 Python 时就写 Python ，而只在必须使用 C 时写 C .

（在此之后，我开始在我的访谈中指出我所谓的 “Perl 的教训” ，也就是任何一个没有和 C 语言语义等价的 POSIX 绑定的语言_都得失败_。在计算机科学的发展史上，作者没有意识到这一点的学术语言的骨骸俯拾皆是。）

显然，对我来说，，Python 的主要优势之一就是它很简单，当我写 Python 时，我不再需要担心内存管理问题或者会导致吐核的程序崩溃 —— 对于 C 程序员来说，处理这些问题烦的要命。而不那么明显的优势恰好在我更改语言时显现，我在 90 年代末写应用程序和非核心系统服务的代码时为了平衡成本与风险都会倾向于选择具有自动内存管理但是开销更大的语言，以抵消之前提到的 C 语言的缺陷。而在仅仅几年之前（甚至是 1990 年），那些语言的开销还是大到无法承受的；那时摩尔定律还没让硬件产业迅猛发展。

与 C 相比更喜欢 Python —— 然后只要是能的话我就会从 C 语言转移到 Python ，这让我的工作的复杂程度降了不少。我开始在 GPSD 以及 NTPsec 里面加入 Python。这就是我们能把 NTP 的代码库大小削减四分之一的原因。

但是今天我不是来讲 Python 的。尽管我觉得它在竞争中脱颖而出，Python 也不是在 2000 年之前彻底结束我在新项目上使用 C 语言的原因，在当时任何一个新的学院派的动态语言都可以让我不写 C 语言代码。那件事可能是在我写了很多 Java 之后发生的，这就是另一段时间线了。

我写这个回忆录部分原因是我觉得我不特殊，我像在世纪之交，同样的事件也改变了不少 C 语言老手的编码习惯。他们也会和我之前一样，没有发现这一转变。

在 2000 年以后，尽管我还在使用 C/C++ 写之前的项目，比如 GPSD ，游戏韦诺之战以及 NTPsec，但是我的所有新项目都是使用 Python 的。

有很多程序是在完全无法在 C 语言下写出来的，尤其是 [reposurgeon][4] 以及 [doclifter][5] 这样的项目。由于 C 语言的有限的数据本体以及其脆弱的底层管理，尝试用 C 写的话可能会很恐怖，并注定失败。

甚至是对于更小的项目 —— 那些可以在 C 中实现的东西 —— 我也使用 Python 写，因为我不想花不必要的时间以及精力去处理内核转储问题。这种情况一直持续到去年年底，持续到我创建我的第一个 Rust 项目，以及成功写出第一个[使用 Go 语言的项目][6]。

如前文所述，尽管我是在讨论我的个人经历，但是我想我的经历体现了时代的趋势。我期待新潮流的出现，而不是仅仅跟随潮流。在 98 年，我是 Python 的早期使用者。来自 [TIOBE][7] 的数据让我在 Go 语言脱胎于公司的实验项目从小众语言火爆的几个月内开始写自己的第一个 Go 语言项目。

总而言之：直到现在第一批有可能挑战 C 语言的传统地位的语言才出现。我判断这个的标砖很简单 —— 只要这个语言能让我等 C 语言老手接受不再写 C 的 事实，这个语言才 “有可能” 挑战到 C 语言的地位 —— 来看啊，这有个新编译器，能把 C 转换到新语言，现在你可以让他完成你的_全部工作_了 —— 这样 C 语言的老手就会开心起来。

Python 以及和其类似的语言对此做的并不够好。使用 Python 实现 NTPsec（以此举例）可能是个灾难，最终会由于过高的运行时开销以及由于垃圾回收机制导致的延迟变化而烂尾。当写单用户且只需要以人类能接受的速度运行的程序时，使用 Python 很好，但是对于以 _机器的速度_ 运行的程序来说就不总是如此了 —— 尤其是在很高的多用户负载之下。这不只是我自己的判断，起初 Go 存在的主要原因就是 Google ，然后 Python 的众多支持者也来支持这款语言 ——— 他们遭遇了同样的痛点。

Go 语言就是为了处理 Python 处理不了的类 C 语言工作而设计的。尽管没有一个全自动语言转换软件让我很是不爽，但是使用 Go 语言来写系统程序对我来说不算麻烦，我发现我写 Go 写的还挺开心的。我的 很多 C 编码技能还可以继续使用，我还收获了垃圾回收机制以及并发编程机制，这何乐而不为？

（[这里][8]有关于我第一次写 Go 的经验的更多信息）

本来我像把 Rust 也视为 “C 语言要过时了” 的例子，但是在学习这们语言并尝试使用这门语言编程之后，我觉得[这语言现在还不行][9]。也许 5 年以后，它才会成为 C 语言的对手。

随着 2017 的临近，我们已经发现了一个相对成熟的语言，其和 C 类似，能够胜任 C 语言的大部分工作场景（我在下面会准确描述），在几年以后，这个语言届的新星可能就会取得成功。

这件事意义重大。如果你不长远地回顾历史，你可能看不出来这件事情的伟大性。_三十年了_ —— 这几乎就是我写代码的时间，我们都没有等到 C 语言的继任者。也无法体验在前 C 语言时代的系统编程是什么模样。但是现在我们可以使用两种视角来看待系统编程...

...另一个视角就是下面这个语言。我的一个朋友正在开发一个他称之为 "Cx" 的语言，这个语言在 C 语言上做了很少的改动，使得其能够支持类型安全；他的项目的目的就是要创建一个能够在最少人力参与的情况下把古典 C 语言修改为新语言的程序。我不会指出这位朋友的名字，免得给他太多压力，让他给我做出不切实际的保证，他的实现方法真的很是有意思，我会尽量给他募集资金。

现在，除了 C 语言之外，我看到了三种不同的道路。在两年之前，我一种都不会发现。我重复一遍：这件事情意义重大。

我是说 C 语言将要灭绝吗？没有，在可预见的未来里，C 语言还会在操作系统的内核以及设备固件的编程的主流语言，在那里，尽力压榨硬件性能的古老命令还在奏效，尽管它可能不是那么安全。

现在被攻破的领域就是我之前提到的我经常出没的领域 —— 比如 GPSD 以及 NTPsec ，系统服务以及那些因为历史原因而使用 C 语言写的进程。还有就是以 DNS 服务器以及邮箱 —— 那些得以机器而不是人类的速度运行的系统程序。

现在我们可以预见，未来大多数代码都是由具有强大内存安全特性的 C 语言的替代者实现。Go , Rust 或者 Cx ，无论是哪个， C 的存在都将被弱化。如果我现在来实现 NTP ，我可能就会毫不犹豫的使用 Go 语言来实现。

--------------------------------------------------------------------------------

via: http://esr.ibiblio.org/?p=7711

作者：[Eric Raymond][a]
译者：[name1e5s](https://github.com/name1e5s)
校对：[校对者ID](https://github.com/校对者ID)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出

[a]:http://esr.ibiblio.org/?author=2
[1]:http://esr.ibiblio.org/?author=2
[2]:http://esr.ibiblio.org/?p=7711
[3]:http://sng.sourceforge.net/
[4]:http://www.catb.org/esr/reposurgeon/
[5]:http://www.catb.org/esr/doclifter/
[6]:http://www.catb.org/esr/loccount/
[7]:https://www.tiobe.com/tiobe-index/
[8]:https://blog.ntpsec.org/2017/02/07/grappling-with-go.html
[9]:http://esr.ibiblio.org/?p=7303
