成为一名 Go 程序员的7个阶段

无论你是 Go 新手还是经验丰富的 Gopher,你都可能认识到在 Go 启蒙之路上的这些步骤。

26 Sep 2017 Daisuke Maki

一天上班时,我们在工作聊天室里讨论 Go 编程语言。有一次,我对一个同事的幻灯片进行了评论,说了一些话。

「我认为这就像是成为 Go 程序员的七个阶段中的第三阶段。」

很自然地,我的同事们想知道其余的阶段,所以我简单地概述了一下。以下是成为 Go 程序员的七个阶段,并附有更多的背景资料;看看你是否能在这条路上看到自己。

第一阶段:你相信你可以让 Go 做面向对象的编程

在最初运行A Tour of Go之后,你开始思考 「现在,我怎样才能使这种语言的行为更像面向对象的语言……?」毕竟,你已经习惯了那些东西。你想编写健壮的代码。你想要多态性。

「一定有办法的!」你说,然后你找到了结构嵌入。它允许你巧妙地将包围对象的方法委托给嵌入对象,而不必重复编写代码。很好!

当然,这不是真的。结构嵌入只允许你 委托 方法的调用。即使你看起来像在做多态方法调度,这种关系也不是 IS-A(继承)。它是 HAS-A(包含),所以方法调用的接收者不是包围的对象。接收者始终是方法调用被委托给的嵌入式对象。

你不能在Go中进行面向对象的编程。阶段。

第二阶段:你相信goroutines会解决你所有的问题

你被 Go 的承诺所吸引,认为它可以让你轻松地运行并发代码,它通过goroutines做到了这一点!你所需要做的就是使用go关键字,你可以让几乎所有的函数或方法调用并发运行。那么,你想通过使尽可能多的代码并行运行来最大限度地提高你的代码效率是很自然的。因为你通过让你的函数调用自动创建goroutines来隐藏这一事实,所以调用者甚至不需要意识到这一点。

是的,所以它可能会使你的代码变得更复杂,但是看,现在所有的东西都在并发地运行了!这就是Go。

Go 允许你在不牺牲效率的情况下创建数以百万计的 goroutines,但你真的不应该因为可以使用goroutines 而使用它。并发代码只在单线程中运行的代码更难维护和调试。我的意思是,你有没有认真考虑过,当你从多个 goroutines 中同时访问共享对象时,你的共享对象是否真的被正确同步了?你确定执行的顺序是绝对正确的吗?你真的检查过这些 goroutines 在不再需要时是否真的退出了吗?

Goroutines 最好只在必要时使用,除非你的需求决定了你要在内存中做所有的事情或类似的事情,否则你不应该放弃使用好的旧的多进程模型。

最后,尽量不要在用户背后催生 goroutines,特别是当你在写一个库的时候。明确地使用go调用通常会给用户更多的灵活性和权力。

goroutines只能让你走到这里。只有在真正有意义的时候才使用它们。

第三阶段:你相信,代替面向对象的编程,接口会解决你所有的问题

在对不能使你的对象以多态的方式行为感到失望之后,你突然意识到接口所提供的能力。接口允许你描述API;一定有办法利用它来编写更健壮的代码。

所以现在当你写库的时候,你为所有东西都定义了接口。你只输出接口,并拥有私有结构,这样封装就很完美了。这也会让你在切换底层实现时有更大的灵活性,因为现在你已经成功地将 API 和它的实现解耦了。

接口 确实 给了你很大的权力,但它不是一个全能的解决方案。它仍然没有提供面向对象编程意义上的真正的多态性。你还受限于这样一个事实,即接口只能定义 API,而你不能将任何数据与之关联。

另外,尽管在一些合理的情况下,只导出接口而不是具体的结构体是有意义的,但它真的不应该成为你的默认操作模式。当接口很小的时候是最好的(相对于描述为一个对象定义的整个方法列表而言)。另外,如果你不小心,你将不得不写很多额外的代码来实现接口,或者写需要很多类型断言的代码。

为了最大限度地利用接口,你应该只在你想让某些类型可以互换时才使用它们。

第四阶段:你相信 channels 会解决你所有的问题

在你花了很多时间思考如何让 Go 按你的方式工作之后,你现在正在寻找那个缺失的部分,以使一切都按你的方式工作。「 等等,还有 channels!」

channels 隐含地正确处理了并发访问。你相信通过巧妙地使用 channels 来处理同步、返回值(la future/promises),以及用各种 channels 的 select 语句进行流控制,你应该能够解决到目前为止的许多障碍。

同样,channels 是非常有用的,但它们的作用只和它们最初的目的一样,即提供一个在 goroutines 之间传递数值的基元。

我相信你会发现很多 Go 的习性都在使用通道:用于超时、阻塞 I/O、同步技巧等等。但是,因为通道是并发结构,滥用它们会导致更复杂的、难以调试的代码。

第五阶段:你现在认为 Go 并不像人们所说的那样强大

“为什么?为什么写 Go 代码这么痛苦?它不允许我以我一直以来的方式写代码”。

你感到很沮丧。没有多态性。并发是很难的。通道并不能解决你的问题。你甚至不明白为什么 Go会存在。你觉得你已经被剥夺了其他语言提供的所有好的工具和结构。

你认为更强大的工具来表达抽象的想法是绝对必要的。Go 就是不适合。

Go 是绝对有主见的。我的前一门语言是Perl,有一段时间我无法相信Go的局限性有多大。所以是的,如果你变得很沮丧,我可以理解。

但这是因为这门语言确实有局限性,还是因为你试图让这门语言按照你认为的方式工作,而没有考虑到语言作者希望你做什么?

第六阶段:你意识到1-5阶段都只是你的想象力

在某个时候,你勉强决定按照大多数标准库的写法来写Go代码。你也放弃了聪明的尝试,开始写简单的代码。

然后你就想到了。你只是不想接受Go的方式。

一切都开始变得有意义了。

说实在的,学习 Go 确实需要一些不学习的东西。我不得不放弃学习面向对象的编程,同时也要接受这样一个事实:无论语言给你提供多少有用的工具,编写并发代码对凡人来说都太难了。我也不得不停止学习使用异常。

我没有向 Go 的作者核实,所以这只是我的看法,但我相信这门语言的重点是让开发者更难写出复杂的代码。它让你有足够的能力来编写执行复杂任务的代码,但通过拿走某些关键工具,你最终写出的代码更简单,更难搞。

一旦我决定接受功能和结构的现状,写 GO 代码就变得容易多了,而且肯定会更有趣。

第七阶段。你现在很平静

你已经接受了 Go 的方式。你现在写所有的东西,包括你通常会用 Perl/Ruby/Python 写的东西,都用 Go。你意识到 if err != nil 已经不再困扰你了。你只在必要时使用 goroutines 和 channel。

你与 Gopher 融为一体。 你感受到了它的光辉之气,当你意识到它允许你用如此雄伟的语言写代码时,你会哭。

恭喜你。现在你是一个 Go 程序员了。


尽管这听起来有点口无遮拦,但这些都是我在习惯Go时感受或经历的实际问题。也许你同意,也许你不同意,但第六阶段对我来说其实是这样的。我最终放弃了让 Go 像 想的那样工作,决定按 Go 告诉我的方式来写。这听起来很傻,但在那之后,事情真的开始变得有意义了。

希望新手 Gophers 能少浪费一些时间来琢磨如何扭曲语言而受挫。祝你骇客愉快

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://opensource.com/article/17/9/seve...

译文地址:https://learnku.com/go/t/65253

本帖已被设为精华帖!
本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
讨论数量: 6
DonnyLiu

跟某度上面的写的文章不是一个档次,高人 :joy:

2年前 评论
zhaocrazy (楼主) 2年前

第二阶段,路过!哈哈哈

2年前 评论
chowjiawei

我就学了一点 就很平静了 :joy:

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!