专栏名称: 唤之
目录
相关文章推荐
OSC开源社区  ·  李彦宏:DeepSeek让我们明白要将最优秀 ... ·  昨天  
程序猿  ·  TCP 才不傻! ·  2 天前  
程序猿  ·  问问DeepSeek,你和ChatGPT谁厉 ... ·  昨天  
程序员小灰  ·  DeepSeek创始人梁文峰牛逼的个人经历 ·  昨天  
码农翻身  ·  Bill Gates 和 Linus ... ·  2 天前  
51好读  ›  专栏  ›  唤之

Go的美好或者丑陋

唤之  · 掘金  · 程序员  · 2018-04-19 02:54

正文

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

琪花亿草 琪花亿草 翻译于 3天前 0人顶 翻译得不错哦!

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

Tocy Tocy 翻译于 6天前 0人顶 翻译得不错哦!

这是篇长文,所以,这是让你开胃口的菜单目录:

好的

Go易于学习

易于并发编程的协程(goroutines )和通道(channels)

强大的标准库

高性能GO

程序语言定义的源代码格式

Defer声明,避免忘记清理

新类型

不好之处

GO忽略现代语言设计的进步

接口是结构类型

没有枚举

:= / var的困境

(让人)恐慌的零值

Go没有异常

烂的

依赖关系管理的噩梦

用语言硬编码的 可变性

Slice陷阱

可变性和渠道:使竞态条件(race conditions)很容易

混乱的错误管理

Nil接口值

Struct字段标记:字符串中的运行时DSL

没有泛型…至少不是为了你

Go在slice和map之外几乎没有什么数据结构

go generate: ok-ish,但是…

结语

Tot_ziens Tot_ziens 翻译于 6天前 0人顶 翻译得不错哦!

优点

Go容易学习

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

琪花亿草 琪花亿草 翻译于 5天前 0人顶 翻译得不错哦!

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

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

琪花亿草 琪花亿草 翻译于 5天前 0人顶 翻译得不错哦!

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



琪花亿草 琪花亿草 翻译于 5天前 0人顶 翻译得不错哦!

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

强大的标准库

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







请到「今天看啥」查看全文