Golang不利于重构升级? - fasterthanli


本文作者曾经发布《我想离开Golang先生的狂野之旅》,该文反复出现在Reddit、Lobste.rs、HackerNews等地方引起广泛争议,本文是其最新文章,主要指出go虽然很容易上手,但是随着系统复杂就很难拓展了,下面是摘录:

显然,Go团队并不想设计一种语言。他们真正喜欢的是他们的异步运行方式:他们希望能够在此基础上实现TCP、HTTP、TLS、HTTP/2和DNS等,然后在所有这些的基础上实现网络服务。

所以他们并没有打算设计一种真正语言。

Go只是需要让 刚从学校毕业的Googlers熟悉,他们可能学过一些Java/C/C++/Python"(Rob Pike, Lang NEXT 2014),所以它借用了所有这些语言。

就像C语言一样,它完全不关心错误处理:
所有的东西都是一个大的毛茸茸的可变状态的泥球,你需要添加ifs和els来非常谨慎地(非常手动地)确保你不会传播无效的数据。

可变状态
就像 Java 一样,它试图消除“值”和“引用”之间的区别,因此无法从调用站点判断某些内容是否发生了变异:

import "fmt"

type A struct {
    Value int
}

func main() {
    a := A{Value: 1}
    a.Change()
    fmt.Printf(
"a.Value = %d\n", a.Value)
}

上面代码依赖于下面两种函数实现:

func (a A) Change() {
    a.Value = 2
}
func (a *A) Change() {
    a.Value = 2
}

而且,就像C和Java一样,你不能决定什么是可变的,什么是不可变的(C中的const关键字基本上是咨询性的,有点),传递一个引用(例如,为了避免昂贵的复制)充满了风险,比如它从你脚下被变异,或者它被永远保存在某个地方,阻止它被释放(一个较小,但非常真实的问题)。

Go未能防止许多其他类型的错误:它使人们很容易意外地复制一个mutex,使其完全失效,或者使结构字段未被初始化(或者说,初始化为零值),导致无数的逻辑错误。

Rust和Go

  1. Go的成功在很大程度上是由于它有包括电池和意见的默认值。
  2. Rust的成功在很大程度上是由于它很容易被零散地采用,并与其他人打成一片。

他们都是成功的故事,只是非常不同。

Go 作为原型设计/入门语言
Go 很可能不足以用于生产服务,但肯定还是有一席之地的。
毕竟,Go 是一门容易上手的语言(因为它太小了,对吧?),而且现在很多人都学过它,所以很容易招募 Go 开发人员,所以我们可以以便宜的价格获得大量的开发人员开发几个原型系统?

然后当事情变得困难时(就像他们总是大规模地做的那样),我们要么将其重写(重构)为其他东西,要么我们会聘请专家,我们会想出办法。

我所见过的所有工程组织都非常不喜欢重写(重构),这是有原因的!他们需要时间,协调无缝过渡是很难的,细节会在混乱中丢失,你在做这些的时候并没有交付新的功能,你必须重新培训你的员工来有效地处理新的功能。
他们需要时间,安排一个无缝的过渡是很难的,细节会在混乱中丢失,你在做这些事情的时候不会产生新的功能,你必须重新培训你的员工,使他们在新的事情上有效等等。

所以很少有东西最终会被重写(重构)。
随着越来越多的组件用Go编写,有越来越多的理由继续这样做:不是因为它对你的工作特别好,而是因为与现有代码库的互动,从字面上看,其他任何东西都是非常痛苦的。

所有 Go 的陷阱,语言和编译器无法帮助您预防的所有事情,对每个人来说都是一个问题,无论是新手还是经验丰富的人。

因为Go有很多值得喜欢的地方,因为它很容易上手,但却很难离开,因为当初选择它的代价会随着时间的推移慢慢显现出来,而且会不断增加,直到为时已晚才会变得难以忍受,作为一个行业,这不是我们可以忽视的讨论。

详细点击标题