对比学习 Go 和 Rust:序

2022年1月4日 // Go Rust 编程

介绍

Go 和 Rust 首次公开分别是 2009 年和 2010 年,是两种相对比较新的语言,在发布时都自称为系统级编程语言,并在发布后都获得了广泛的关注和应用。两者的特征和应用领域有一定的重合,但也差异显著。许多人在最初会选择其中一个,但后来往往由于特定的应用需求,或仅仅出于好学,会进一步选择另外一种语言。对于像我这样水平一般的人,同时学习多种语言是比较困难的,经常是学会一个而忘记另外一个。为了能同时学会这两种语言,最好是对两者的各个关键知识点进行深入的对比,弄清这些关键知识点的主要区别、设计初衷、优缺点、惯用法等。这种学习方法会非常累人,但也卓有成效。在学习过程中,我将会把学习成果整理为你所看到的这个 《对比学习 Go 和 Rust》 的系列学习笔记。希望通过此笔记整理自己的学习成果,供自己日后查阅,同时也希望能为同样同时学习 Go 和 Rust 的朋友提供参考。

鉴于目前已经有很多关于 Go 和 Rust 语言的学习资料了,此系列笔记将会略过一些简单的内容,尽量做到简明扼要,也不强调系统性。因此,此系列笔记只能作为同时学习这两门语言的辅助材料,且不适合初学者。

简单对比

关于这两种语言的介绍资料已经有很多了,这里只给出两句话介绍:

  • Go 是一个通用的系统级编程语言,具有表达能力强、简洁、干净和高效的特点,可用于构建大型、快速、可靠和高效的软件。
  • Rust 也是一种通用的系统级编程语言,具有高性能、可靠和生产力强的特点,可用于构建可靠且高效的软件。

Go 和 Rust 有许多共同的特征,两者同时配享有如下标签:现代、开源、通用、编译型、强类型、表达力强、高性能、高并发、内存安全、模块化、可扩展、跨平台,等等。

两者的差异主要表现在:

  • 简单性:Go 很简单,在特性选择上属于够用就好,很多特性像动态脚本语言一样灵活,因此易学易用;Rust 则复杂得多,包含许多强大且有用的特性,因此具有较多的编程范式,实现相同功能其代码量会更少,但难以学习。
  • 性能:两者都被编译为原生机器码,因此 Go 不弱,但 Rust 很强;Rust 的设计遵循零开销抽象的原则,使其能在特性丰富的同时保持高性能,实属不易。
  • 编译速度:Go 很快,Rust 比较慢。
  • 内存安全:Go 通过自动垃圾回收实现类型安全,而 Rust 则创新性地通过所有权系统、借用和生命周期实现类型安全,。
  • 并发支持:对并发的原生支持是 Go 的重要特色,Rust 当然也可以进行并发编程,但不如 Go 成熟和容易。
  • 可控性:Rust 更接近计算机底层,能更精确地管理计算机内存及其他资源。
  • 一致性:Go 语言的简单看起来有点像黑魔法,其内部实现和语言要求是不一致的,Rust 则更为一致。
  • 错误处理:Go 的错误处理方法经常引起争议,Rust 在这方面则较少争议。
  • 生态:相对于 Rust,Go 更成熟,相关代码库的数量也更多,因此生态更好。
  • 应用领域:Go 常用来写 Web 应用、数据库开发、网络编程。Rust 适合用来写命令行、网络服务、WebAssembly、嵌入式程序,等等。其中命令行和网络服务用 Go 也完全可以胜任,在 WebAssembly 领域 Go 不如 Rust,而在嵌入式领域 Go 则更难胜任。

这两种语言的编程思想存在较大的差异。Go 语言的编程思想基本上可用“大道至简”来形容,即只往语言中添加一些必不可少的特性,从而使其保持简洁和干净。而 Rust 则为了实现内存安全、高性能、零开销抽象等目标而绞尽脑汁,可谓无所不用其极。这导致 Rust 看起来有点怪异、学究气,学习曲线陡峭,不过好在 Rust 已经构建了一套完整的体系,实现了自己的目标。

如何选择?

在学习 Go 后再学 Rust,经常会在心中有这样的吐槽:“这项设置为什么不能像 Go 那样简单?”从实用的角度来看,我觉得 Rust 的确存在许多不必要的复杂。要不然,就冲 Rust 的许多绝杀技,我会毫不犹豫地选择 Rust。

如果要在两种语言间进行选择的话,我自己会在够用的前提下,尽量选择 Go 语言,因为它真的更简单易学,这也使其利于团队间的交流协作。但有时 Go 会不够用,如需要编写要求极致性能的程序,需要精确地调度计算资源,需要使用 WebAssembly 技术编写复杂且高性能的 Web 应用,或者进行嵌入式开发,这时用 Rust 将会是更好的选择。当然,同时学会这两种语言,分别将他们应用于不同的场景中,这将会更好,只是付出的代价也相对较大而已。

安装和更新

这里只介绍在 Linux 操作系统下的安装和更新。许多 Linux 发行版的软件仓库中已经有 Go 或 Rust 了,但常常又不是最新版本,因此这里介绍如何手动安装最新版本。

安装

Go 语言的安装步骤:

  1. 官网(或国内镜像)下载对应版本、对应操作系统、对应处理器架构的安装包,如 go1.17.6.linux-amd64.tar.gz,将其内容解压到 /usr/local 目录中,这将创建 /usr/local/go 目录树:

    wget https://golang.google.cn/dl/go1.17.6.linux-amd64.tar.gz
    sudo rm -rf /usr/local/go
    sudo tar -C /usr/local -xzf go1.17.6.linux-amd64.tar.gz
    
  2. /usr/local/go/bin 添加到 PATH 环境变量列表中,这可通过在 $HOME/.profile/etc/profile(对操作系统全局安装时选择)文件中添加如下一行:

    export PATH=$PATH:/usr/local/go/bin
    

    可通过运行 source $HOME/.profile 使以上改动快速生效。

  3. 通过运行以下命令验证安装是否成功:

    $ go version
    

    如果打印正确的版本,如 go version go1.17.6 linux/amd64,则表明安装成功。

Rust 语言的安装步骤:

  1. 类 Unix 系统中一般运行如下命令通过 rustup 脚本安装 Rust:

    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
    

    这将在 $HOME/.cargo 目录装安装 Rust。以上命令同时会自动将 Rust 的二进制文件路径添加到 PATH 环境变量中, 通常在 .profile 文件的末尾可以看到如下一行:

    export PATH="$HOME/.cargo/bin:$PATH"
    

    可通过运行 source $HOME/.profile 使以上改动快速生效。

  2. 通过运行以下命令验证安装是否成功:

    cargo --version
    

    如果打印正确的版本,如 cargo 1.57.0 (b2e52d7ca 2021-10-21),则表明安装成功。

更新

要更新 Go,请重复以上安装步骤的第一步。即直接下载最新的安装包,并覆盖已有的安装包。

要更新 Rust,请运行如下命令:

rustup update

卸载

要卸载 Go,请首先删除 /usr/local/go 目录:

sudo rm -rf /usr/local/go

然后再删除 $HOME/.profile/etc/profile 文件中的如下一行:

export PATH=$PATH:/usr/local/go/bin

要卸载 Rust,请运行如下命令:

rustup self uninstall

Hello, world! 程序

最后,就像大多数初次入门教程那样,奉上这两门语言的 Hello, world! 程序代码。

Go:

package main

import "fmt"

func main() {
    fmt.Printf("Hello, world!\n")
}

Rust:

fn main() {
    println!("Hello, world!");
}