<audio id="audio" title="第22讲 | 如何选择合适的开发语言？" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/e1/f6/e1216f72adbe0e7fa57338dc3cfb0cf6.mp3"></audio>

有许多编程语言可以用来开发服务器端。一些语言对于网络开发有先天优势，一些语言没有先天优势，但是能完成任务，而有一些语言，则不太适合。今天，我就来具体讲一讲这些语言来开发网络服务的优劣势。

## 你了解这些编程语言吗？

**C/C++** 是最标准的开发语言，速度快，并发性能高，能最大程度利用机器资源完成任务。现在C/C++层面拥有无数网络开发库和SDK，知名的有ACE、Boost/Asio、ICE等等。但是缺点是，开发效率不比别的语言来得高，出错后常常只有熟练的程序员才能定位问题并且作出修复。

**Go**是2009年新出现的语言。Go天生适合编写网络程序。它也是一种系统级的语言，可以直接编译为执行文件，当然由于封装了大量的语法糖，所以编译出来的文件会更大，它天生支持并发操作，所以很多时候你不需要像C/C++一样手工去处理。缺点是，Go语言仍然存在许多语法方面的坑，你可以去 [https://studygolang.com/](https://studygolang.com/) 学习最新的资料。

**Java**是公认的编写网络服务的第一大语言。在运行性能和开发效率上，有很好的折中效果。Java拥有众多的中间件和开发库，调试方便，一般的运维人员也有极为广泛可用的第三方维护工具可以使用。缺点是，Java的运行效率虽然有了质的飞跃，但因为中间隔了一层虚拟机，所以仍然比不上系统开发语言编写的软件。另外，Java的发布和部署需要众多的依赖包和库，软件体积庞大也是其重要弊病。

如果深入理解，**Python、Ruby**这两种语言的相似程度以及对系统的支持程度，可以用C和C++的相似程度来相比。你或许会很疑惑，毕竟Python和Ruby的语法几乎不一样，Python需要格式化源代码，而Ruby并不需要；Python更严谨，Ruby更开放；Python用户更多，Ruby用户更少。

不可否认的是，两种语言编写网络程序都非常方便，也非常高效。两种语言都可以在100行内编写出一个简单的、完全可以直接使用的网络服务器程序。但是这两种语言的弊病也很明显，那就是速度不够快。

比之Java，或许运行效率更慢一点，但由于目前机器硬件水平的提升，软件效率不足的缺点一部分已经被硬件所弥补，但是仍然不能否认，Python、Ruby语言适合IO密集型开发，而不适合计算密集型的开发。

Python的书籍比Ruby多好几倍，然而你如果仔细去看的话就会发现，Ruby的书籍质量明显比Python高几个等级，所以如果要看好的脚本语言的书籍，Ruby相关的书籍是首选，我这里推荐一本[Programming in Ruby](https://book.douban.com/subject/2032343/)，有兴趣的话可以找来看看。

**Node.js**从前端语言变成后端语言，让编程界眼前为之一亮。随后的发展大家也有目共睹，Node.js由于使用JavaScript语言语法，所以我们一般采用事件驱动的形式，以及非阻塞的模型来进行网络开发。因为这些特点，它非常适合做分布式的、数据密集型的工作。但是缺点也很明显，Node.js是单线程，无法很好地使用多核CPU，这个问题在Python、Ruby语言中也很明显。

或许你没有听说过**Erlang**这种语言，这种语言最初是由爱立信开发的。它的初衷是让程序员应对大规模并发、分布式、软件实时并行系统进行编程。最早期的版本在80年代就出现了，但是一直到1998年才开源。

Erlang也不是系统语言，它有自己的虚拟机和解释器。当然和Java一样，Erlang也支持将代码编译为Native Code来运行。Erlang的缺点就是类型问题，它并非强类型语言。由于是事件编程，所以导致会在运行时无法匹配类型而出错，不过这些问题可以使用规范的编程方法来规避。

这么多种编程语言，整合起来看，大致可以把他们分为三类。

**系统级编程语言**，诸如汇编、C、C++。这种编程语言执行效率快，并发量也比较高，作为编写网络服务的第一语言，一台服务器就能支撑许多人。缺点是开发效率不够高，需要几年以上经验的程序员才能搞定。

**专门为网络服务器开发的语言**，诸如Go、Erlang。这种语言编写高并发和开发效率都不是问题，有很好的折中效果。缺点就是语言比较新，有许多的坑等着后来的程序员去填，而且语言、语法等系统机制要随着进一步的发展才能稳定下来。

**解释型脚本语言**，诸如Python、Ruby。 这类语言的开发效率非常高效，在现在的服务器硬件上，也能支撑不少用户，但是唯一的缺点是，运行效率低下。虽然也有解决方案，但仍然不能对抗高性能的系统编程语言和专业网络开发的语言。

## 如何选择一种合适的语言来编写网络服务？

### Web服务

现在有一种流行的说法叫前后端分离。对于编写C/S结构的程序员，听到这种说法应该会比较蒙，客户端和服务器端难道不是本来就分离的吗？

很长的一段时间里，在Web的世界中，前后端都是混合在一起编写的，比如PHP的方式，只有用到Ajax交互的时候，才需要用到后端的代码。但是前后端一分离，后台就需要做更多的工作了，当然前端的工作也不会变少。

编写Web服务，需要HTTP和HTTPS的服务体系，那么在这种情况下，使用nginx、Apache作为静态页面路由，Java、Tomcat、Python、Ruby等脚本语言就有了用武之地。因为页面只需要使用JSON交互即可。

所以，编写Web服务，我们可以选择Java、Python、Ruby。但是如果公司财力物力有限，再考虑到招人成本的问题，次选也可以是Java语言，第一是写Java的人够多，第二是Java成熟的类库够多，因此，一旦出问题，有解决经验的人也比较多。

### Socket服务

传统TCP/IP和UDP服务，或者最近的WebSocket等，都需要快速响应和并发操作，在这种情况下，系统级编程语言和网络编程语言就可以派上用场了。

如果公司的项目需要更快更高效，并且财力也允许，那么选择C、C++、Go、Erlang等编程语言未尝不是一种选择。当然Java也能很好地提供服务，但是从业务上来讲，既然选择了Socket服务模式，那么就必然是对并发量有一定的要求，所以选择上述这些语言更合适。

### 混合模式

这类业务，既有HTTP/HTTPS的服务，也有Socket服务，那么如何平衡两者之间的语言成本？如何平衡程序员之间技术栈的问题呢？

如果要做一款短期内必须上线的产品，我建议选择成熟的、有大量解决方案的，开发人员不短缺的语言，比如Java；或者能快速做出原型的语言，比如服务器专有语言Go。如果是长期发展的产品，并不那么着急成型，那么选择稳定成熟的，人员素质高的语言，比如Python、Java等。

至于平衡技术栈的问题，首先要选择网上有众多解决方案的语言，其次是找成熟的语言，比如Python、Java、Ruby。如果针对某种特殊的产品，比如并发要求特别高的，那么只有选择系统语言或者专门的语言，比如Go、C++等。

看到这里，你是不是觉得Java语言是一种万能药，或者是银弹？错了，这个世界上没有银弹。Java虽然有其独特的优势，但是其被人诟病的地方，也是有不少的。

第一点莫过于速度。就算拥有JIT编译，总体速度仍然比不上C/C++，但是事实上这些因素综合考虑并不算特别大的弊病，因为硬件资源提升后，速度这些问题已经可以“得过且过”了。

那么从语言本身来看，如果说C/C++语言本身的弊病是因为系统平台导致的，那么Java语言的弊病就是因为继承自C++，却没有做更彻底的改革而导致的。

我随便举一个例子，比如说switch case判断语句，硬生生地从C/C++处直接继承了下来，因为C/C++只允许使用int、enum（其实是int）、char（提升为int）作为判断类型，而Java也是直接将这套规范继承了下来。

再比如，在Java里面，异常检查也是一个痛苦的根源，程序员不得不写下无数try catch语句以使得将捕获的异常，转变为运行时的异常，然后再将之抛出去，这样一来，使用Java编写的API将缺少灵活和扩展性。

那如果选择了Python或者Ruby等脚本语言进行开发，却需要大量高并发的操作该怎么办呢？我们可以选择多进程（不是多线程）编程的方式进行开发，代码尽量简洁、高效，一个进程兼顾一个任务，进程之间的通信方式要尽量高效、简洁，比如可以使用自定义的队列等方式。

## 小结

学完这一节，你应该对使用各种编程语言来编写网络服务有了一个更深的了解。我主要讲了以下几个内容。

<li>
编程语言可以大致分为三类，系统级编程语言、专为网络服务器开发的编程语言和解释型脚本语言。
</li>
<li>
在编写网络服务的时候，可以根据要编写的是Web服务、Socket服务，还是混合模式，来选择合适的编程语言。
</li>

给你留一个小问题吧。

如果让你来使用C/C++粘合Lua脚本来编写网络服务器，你会怎么设计这个程序框架？

欢迎留言说出你的看法。我在下一节的挑战中等你！
