Go程序员如何学习Rust? - Reddit


问:我使用Go已经超过3年了,我喜欢这门语言,尤其是语法。但我也对人们抱怨的那些常见的怪癖感到有些恼火。我觉得在过去的两年多时间里,对Go的抱怨多了起来,而且有些是经过深思熟虑的批评。我想蜜月期已经结束了。
我一年多前开始学习Rust,到现在为止,我唯一的烦恼是它的语法汤。除此以外,内存模型非常棒,尽管它会影响编程速度。我认为Rust还处于蜜月期,人们最终会发现它的问题,特别是当它变得无处不在的时候。对于那些也学过它的人来说,你对这种语言有什么看法?

答:
1、Go和Rust我都使用过,尽管使用Golang比Rust机会多得多。
Rust是一种非常通用的强大语言,我发现Rust有3个方面非常有用,而Golang却没有:

  • 强大的函数式范式,使所有的东西都比Go至少少一半的行数。
  • 宏系统,它允许干净和通用的解决方案,通用性,Go现在还在开发。
  • 内存安全和性能:这里有很多东西要讲,但最核心的是。如果你知道自己在做什么的话,没有GC会给你带来巨大的性能优势。而Rust让你很容易找到正确的解决方案。

2、两年前,Go是我个人项目的主要语言,直到我决定给Rust一个机会,看看所有的炒作是怎么回事。老实说,我已经无法回头了。Rust的属性系统、枚举、错误处理、函数式编程方面、默认的不可更改性、ffi接口、元编程结构、借贷检查器,以及所有这些都使它成为一门令人愉快和符合人体工程学的语言。

是的,Rust有一个巨大的学习曲线,是的,Rust有一个大得多的语法,这可能会给人们带来选择的麻痹,但最终Rust所做的一切都不是多余的。如果你不需要X,就不要使用X,它可以根据你的需要变得简单。

能够写出复杂的程序,而这些程序员从Unix时代开始就被大多数错误所困扰--纠缠的指针、使用后的自由、双重自由、空指针异常、数据竞赛、缓冲区溢出等等--使得Rust成为现代编程语言的理想榜样。

下面这段代码这可以在 Go 中编译的事实确实令人担忧


package main

import (
    "fmt"
    "sync"
)

func main() {
    foo := 0

    var wg sync.WaitGroup

    for i := 0; i < 100; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            foo += 1
        }()
    }

    wg.Wait()

    fmt.Println("%d", foo)
}

每个 goroutine 使用相同的变量, Go 编译器能够防止这种情况发生吗?

因为有多个 goroutines 共享对同一块内存的并发写访问,这块内存既不受原子指令保护,也不受互斥锁保护,也没有任何其他同步机制导致数据竞争,从而产生不一致的结果,从而产生未定义的行为。

这是 Rust 编译器会立即标记并阻止程序编译这类代码。

当然,这可能不是 Go 语言开发人员优先考虑的事情。他们优先考虑简单性、易用性、易学性和编译速度。他们付出的代价成本就是程序员仍然容易受到上面提到的常见错误类别的影响。
Rust优先考虑性能、功能丰富和内存安全。他们付出的机会成本是编译器必须更努力地工作,以获得这些编译时的保证,从而使编译速度变慢。在我看来,这是一个很小的代价。


3、我使用Go已经有好几年了,使用Rust也有两年多了,并在这两个领域部署了生产服务。

我喜欢Rust,在未来,我希望我将更多地使用它,可能比Go更多。这并不是说我不喜欢Go;我仍然认为它是一种伟大的语言/平台,我将继续使用它。

我发现通过像tokio这样的东西,我可以得到一个至少和Go运行时一样好的运行时,同时还有一个更具表现力的类型系统,一个支持我的编译器和真正的英雄:借贷检查器。

我发现我对推送到生产中的代码更有信心;在Rust中,如果它能编译,就有很大的可能是正确的,这一点在Go中并不存在,至少没有达到相同程度。

互操作的故事也要好得多,这对我来说很有用,但对其他人来说可能就不那么重要了,这取决于手头的工作种类。

编译时间比较慢,但也不是真的慢。除非你工作在有大量链接或proc宏的非常大的代码库上,否则它是非常可行的。

在我看来,它是非常值得的,因为学习曲线很陡峭。

编辑:另外值得一提的是。现在我觉得我对Go的熟练程度比以前高多了,因为我知道Rust。它迫使你思考所有权的方式改变了你对其他语言的思考方式,这也是Rust产生的最好的东西之一。

4、现在Rust的构建/测试循环周期是否更快?
说实话,这是我最大的不满......编译/运行/测试什么东西需要多长时间。我不是一个修复了8个不同的东西然后构建/运行/测试所有这些东西的开发者。我倾向于做一个改变,构建/测试,如果不对的话再回去做一遍。这就是Go最大的诱惑之一......它疯狂的构建/运行/测试周期。我觉得用Go比用JavaPython、Node等更有成效。

我接触过Rust......它看起来并不坏......但我读到它的速度要慢得多。那是几年前的事了(是构建速度慢,而不是运行速度)。现在的速度是相当快,还是仍然在快速修复/构建/测试周期中挣扎?

还有...但Rust能像Go那样编译到不同的平台上吗......还是说你必须在你要构建的特定机器上安装和构建?

最后,Rust是否支持代码的动态链接加载?插件?如果是的话...在所有的平台上?Go有一个插件功能,但它是一个很糟糕的东西......只适用于Linux,在Mac(M1之前)上有一些,而且不能处理不同版本的Go编译模块。因此,如果你从Go 1.18.1更新到1.18.2,并在1.18.2中构建一个模块与1.18.1的应用程序一起运行,那将是一场噩梦。我不明白为什么在这种情况下会出现这样的问题。Rust是否避免了这种不同版本语言的问题......并且很容易支持DLLs(.SO,等等)?

回答:
编译时间是比以前快,这在很大程度上要归功于增量编译的改进。它仍然没有Go那么快,但正如我所说的,它已经足够快了。

动态链接是绝对可能的,而且已经有很长一段时间了。我知道有一些libs在后台使用libcurl和openssl。我的理解是他们坚持使用C ABI,所以如果你用cdylib crate类型编译一个.so,你就基本可以了。

如果你的lib依赖于一个与主程序不一样或不同版本的异步运行时,事情会变得很棘手,但这更像是一个依赖性管理问题,而不是严格意义上的语言问题。

在一个全Rust项目中,标准仍然是静态链接。crates机制使之比C++更容易,这也是Rust中感觉最 "自然 "的地方。


5、我两个都用,我都喜欢。
我认为 Go 的开发非常容易和快速。
Rust 更难,更难让初级人员精通,因为它是一种更难的语法,需要考虑借用、生命周期等更多事情。
我考虑使用编程语言工具来解决问题。

Go 很容易,特别是对于新开发人员而言,这意味着更快的开发时间。

我知道有几家公司全力投入 Rust,将它用于简单的 Rest API,流量非常低。
在那些情况下,我认为他们犯了一个错误,开发时间会更长,而且他们不会真正从性能中受益,因为这不会成为问题或在云中运行的成本特别高。
我会推荐任何构建没有任何性能需求的软件的团队,Go 的性能足以满足我所说的大多数任务。

由于 Rust 更难,所以每当我有一个非常依赖性能并会从中受益的软件时,我都会使用它。前一段时间我不得不写一个网络流量分析器,这对 Rust 来说是一个完美的案例,以实时速率处理来自多个来源的高速连接,我们不能开始落后,Rust 是一个更好的工具!

我喜欢 Go,因为它很容易开发,而且几乎很无聊。开发速度对我来说意义重大,如果遵循惯用的准则,Go 还可以使程序非常安全可靠。
Rust 可用于在软件中获得额外的冲击力,使其超快速、超安全和出色。但是我很少需要额外的速度,