开源中国

我们不支持 IE 10 及以下版本浏览器

It appears you’re using an unsupported browser

为了获得更好的浏览体验,我们强烈建议您使用较新版本的 Chrome、 Firefox、 Safari 等,或者升级到最新版本的IE浏览器。 如果您使用的是 IE 11 或以上版本,请关闭“兼容性视图”。
美好或者丑陋的 Go - 技术翻译 - 开源中国社区

美好或者丑陋的 Go 【已翻译100%】

标签: Go
oschina 推荐于 2个月前 (共 52 段, 翻译完成于 04-18) 评论 9
收藏  
90
推荐标签: Go 待读

这是一个“Go不好”系列的额外文章。Go确实有一些不错的特性,也就是本文中“好的”部分,但是当我们不使用API或者网络服务器(这是为它设计的)而且将它用于业务领域逻辑的时候,总体而言我发现它用起来笨重且糟糕。但是即使在用于网络编程的时候,在设计和实现方面它也有很多缺陷,这导致它在显而易见的简单的表面之下是危险的。
促使我写这篇文章的原因就是最近我又开始用Go做一个副项目。在我之前的工作我广泛地使用Go来写网络代理(包括http和原生tcp)来做SaaS服务。网络部分相当不错(当时我也是初次尝试这个语言),但是账户和账单部分给我带来了痛苦。由于我的副项目做的是一个简单的API,我觉得Go应该是可以快速完成这个工作的合适的工具,但是就像我们知道的,很多项目会扩张并超过他们的初始范围,因此我不得不写一些数据处理来做统计,然后使用Go就又变得痛苦了。因此下面是我对Go的问题的看法。

琪花亿草
 翻译得不错哦!

一些背景:我喜欢静态类型语言。我的第一个重要项目是用Pascal编写的。在90年代初我开始工作之时,我使用了Ada和C/C ++。后来我迁移到了Java,最后又使用了Scala(在期间还用过Go),最近开始学习Rust。我还写了大量的JavaScript代码,因为直到最近它是Web浏览器中唯一可用的语言。对动态类型语言我感觉不牢靠,并尝试将其应用限制在简单脚本中。我对命令式、函数式和面向对象的方法感到很满意。

Tocy
 翻译得不错哦!

优点

Go容易学习

这是事实:如果你会任何一种编程语言,你可以通过“Go教程”在几个小时之内学会Go的大部分语法,在几天之内就可以写出你的第一个程序。阅读和消化Effective Go,徘徊在标准库中,运用web工具包如Gorilla 或者Go kit,你就能成为一个相当不错的Go开发者。
这是因为Go的首要目标就是简单。当我开始学习Go的时候,它让我回忆起了我初次接触Java:一个丰富却不臃肿的简单语言。与现在的Java繁重的环境对比,学习Go是一个新鲜的体验。由于Go的简单,Go程序是非常易读的,即使错误处理方面有不少麻烦(这下面更多)。
但是这可能并不是真的简单。引用 Rob Pike的话,简单即复杂,我们在下面可以看到在后面有很多的陷阱等着我们,简洁和极简主义阻止了我们编写DRY原则的代码。

琪花亿草
 翻译得不错哦!

使用goroutines 和 channels简单的并发编程

Goroutines可能是Go的最好的特性。与操作系统线程不同,他们是轻量级的计算线程。
当一个Go程序执行阻塞I/O操作一类的工作时,实际上Go实时挂起了这个goroutine,而且在一个event表明一些结果已经可以访问之后,会重新运行。在此期间,其他goroutines已经在为执行调度。因此我们在使用一个同步编程模型做异步编程的时候有可扩展性的优点。
Goroutines也是轻量级的:他们的栈按需增加或减少,也就是说有数百个甚至数千个goroutines都不是问题。

琪花亿草
 翻译得不错哦!

在一个应用中我曾经有一个goroutine泄露:在结束之前这些goroutines等待一个channel去关闭,但那个channel不会关闭(一个常见的死锁问题)。这个进程平白占了90%的CPU,查看expvars显示60万个空的goroutine!我猜CPU都被goroutine调度占用了。
当然,一个像Akka的actor系统可以不费力气就处理数百万actors,一部分是因为actors没有栈,但是他们在写复杂并发request/response应用(如 http APIs)时不如goroutine简单的多。
Channels是goroutines之间交互的通道:他们提供了一个方便的编程模型可以在goroutines之间发送和接收数据,而不用依赖脆弱的底层同步原语。Channels拥有他们自己的一套使用模式



琪花亿草
 翻译得不错哦!

由于错误的channels数量(他们默认无缓冲)会导致死锁,Channels必须要慎重考虑。我们在下面也会提到因为Go缺少不变性,使用channels并不能阻止争抢资源。

强大的标准库

Go标准库真的很强大,特别是对网络协议相关的所有东西或者API开发:http 客户端和服务器,加密,压缩格式,压缩,发送邮件等等。甚至还有html解析器和相当强大的模板引擎,通过自动escaping可以用来产生文字&html来避免XSS(在Hugo 模板的示例中使用)。

琪花亿草
 翻译得不错哦!


大多数情况下APIs通常是简单易懂的。尽管有时候他们看起来过于简单:这当中,一部分是由于goroutine编程模式告诉我们只需要关心“看似同步”的操作。另一部分是因为少数通用的多功能函数能替代大量单一功能的函数,就像最近一段时间,我发现的那些用于时间计算的函数一样。

GO是高性能的

Go编译成一个本地可执行文件。许多Go的用户来自于Python,Ruby或者Node.js。对他们来说,这是个令人兴奋的体验,因为他们发现服务器可以处理的并发请求数量大幅的增加。对于没有并发的语言(Node.js)或者全局解释器锁(GIL)来说,这实际上是再正常不过的事情。结合语言的简单性,这说明了Go语言令人兴奋的一面。

kevinlinkai
 翻译得不错哦!

然而相比Java,在原始性能基准测试中,情况并不是那么清晰。内存使用和垃圾收集方面Go力压Java。

Go的垃圾收集的设计目的是优先考虑延迟和避免stop-the-world停顿,这在服务器中尤其重要。这可能会带来更高的CPU成本,但是在水平可伸缩的架构(horizontally scalable architecture)中通过添加更多的机器这是易于解决的。记住,Go是Google设计的,他们不缺资源。

相比于Java,Go的GC在要做的工作方面更少的:slice的结构是一个连续的结构数组,而不是像Java这样的指针数组。相似地,Go的maps出于同样的目的使用像桶的小数组。这意味着在GC上工作量更少,并且还更有利于CPU的缓存位置。

Go也可以力压Java的命令行实用程序:一个本地可执行的,Go程序对Java的首先必须加载和编译字节码来说没有启动成本。

Tot_ziens
 翻译得不错哦!

语言所定义的源代码格式

在我职业生涯中一些最激烈的争论发生在团队代码格式的定义上。Go通过为Go代码定义规范格式解决了这个问题。gofmt工具会重新格式化你的代码,并且没有选项。

不管喜不喜欢,gofmt都定义了Go代码应该如何格式化,因此该问题得到一次性解决!

标准化的测试框架

Go在其标准库中提供了一个很好的测试框架。它支持并行测试、基准测试,并且包含很多用于轻松测试网络客户端和服务器的使用程序。

Tocy
 翻译得不错哦!
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们
评论(9)
Ctrl/CMD+Enter

消灭零回复
go meitian douyao bei hei ji ci
有些缺陷确实说的很正确,应该慢慢去完善和通过三方库补充
好文章
我很讨厌GOPATH
看进度条以为不长。。。
用了3年多golang,感觉在做基础框架上确实非常好用且高效,不用像其他语言一样需要费很大的劲才能实现,golang天生就支持一些常用的服务;
不好的地方是,感觉不太适合写业务代码,动态更新方面不是很成熟.
go是我目前使用的最爽的语言
依赖管理问题, 数据结构还是太少,缺乏企业级框架(Java这方面好的不要太多),但是啊,多范式,静态编译,灵活&高效。关键还有几个大佬级别的人物牵头,还有Google这样口碑良好的公司Support,这语言还有很长的路要走,但势头很好。: )
顶部