转用一门新语言一般是一项大决策,尤为是当你的团队成员中只有一个使用过它时。今年 Stream 团队的主要编程语言从 Python 转向了 Go。本文解释了其背后的九大缘由以及如何作好这一转换。html
Go的优点java
缘由 1:性能node
Go 极其地快。其性能与 Java 或 C++类似。在咱们的使用中,Go 通常比 Python 要快 30 倍。如下是 Go 与 Java 之间的基准比较:python
缘由 2:语言性能很重要c++
对不少应用来讲,编程语言只是简单充当了其与数据集之间的胶水。语言自己的性能经常无关轻重。git
可是 Stream 是一个 API 提供商,服务于世界 500 强以及超过 2 亿的终端用户。数年来咱们已经优化了 Cassandra、PostgreSQL、Redis 等等,然而最终抵达了所使用语言的极限。程序员
Python 很是棒,可是其在序列化/去序列化、排序和聚合中表现欠佳。咱们常常会遇到这样的问题:Cassandra 用时 1ms 检索了数据,Python 却须要 10ms 将其转化成对象。github
缘由 3:开发者效率&不要过于创新golang
看一下绝佳的入门教程《开始学习 Go 语言》(http://howistart.org/posts/go/1/)中的一小段代码:算法
若是你是一个新手,看到这段代码你并不会感到吃惊。它展现了多种赋值、数据结构、指针、格式化以及内置的 HTTP 库。
当我第一次编程时,我很喜欢使用 Python 的高阶功能。Python 容许你创造性地使用正在编写的代码,好比,你能够:
毋庸置疑这些代码颇有趣,但也使得在读取其余人的工做时,代码变得难以理解。
Go 强迫你坚持打牢基础,这也就为读取任意代码带来了便利,并能很快搞明白当下发生的事情。
注意:固然如何容易仍是要取决于你的使用案例。若是你要建立一个基本的 CRUD API,我仍是建议你使用 Django + DRF,或者 Rails。
缘由 4:并发性&通道
Go 做为一门语言致力于使事情简单化。它并未引入不少新概念,而是聚焦于打造一门简单的语言,它使用起来异常快速而且简单。其惟一的创新之处是 goroutines 和通道。Goroutines 是 Go 面向线程的轻量级方法,而通道是 goroutines 之间通讯的优先方式。
建立 Goroutines 的成本很低,只需几千个字节的额外内存,正因为此,才使得同时运行数百个甚至数千个 goroutines 成为可能。你能够借助通道实现 goroutines 之间的通讯。Go 运行时间能够表示全部的复杂性。Goroutines 以及基于通道的并发性方法使其很是容易使用全部可用的 CPU 内核,并处理并发的 IO——全部不带有复杂的开发。相较于 Python/Java,在一个 goroutine 上运行一个函数须要最小的样板代码。你只需使用关键词「go」添加函数调用:
Go 的并发性方法很是容易上手,相较于 Node 也颇有趣;在 Node 中,开发者必须密切关注异步代码的处理。
并发性的另外一个优质特性是竞赛检测器,这使其很容易弄清楚异步代码中是否存在竞态条件。下面是一些上手 Go 和通道的很好的资源:
缘由 5:快速的编译时间
当前咱们使用 Go 编写的最大微服务的编译时间只需 6 秒。相较于 Java 和 C++呆滞的编译速度,Go 的快速编译时间是一个主要的效率优点。我热爱击剑,可是当我依然记得代码应该作什么之时,事情已经完成就更好了。
Go 以前的代码编译
缘由 6:打造团队的能力
首先,最明显的一点是:Go 的开发者远没有 C++和 Java 等旧语言多。据知,有 38% 的开发者了解 Java,19.3% 的开发者了解 C++,只有 4.6% 的开发者知道 Go。GitHub 数据代表了类似的趋势:相较于 Erlang、Scala 和 Elixir,Go 更为流行,可是相较于 Java 和 C++ 就不是了。
幸运的是 Go 很是简单,且易于学习。它只提供了基本功能而没有多余。Go 引入的新概念是「defer」声明,以及内置的带有 goroutines 和通道的并发性管理。正是因为 Go 的简单性,任何的 Python、Elixir、C++、Scala 或者 Java 开发者皆可在一月内组建成一个高效的 Go 团队。
缘由 7:强大的生态系统
对咱们这么大小的团队(大约 20 人)而言,生态系统很重要。若是你须要重作每块功能,那就没法为客户创造收益了。Go 有着强大的工具支持,面向 Redis、RabbitMQ、PostgreSQL、Template parsing、Task scheduling、Expression parsing 和 RocksDB 的稳定的库。
Go 的生态系统相比于 Rust、Elixir 这样的语言有很大的优点。固然,它又略逊于 Java、Python 或 Node 这样的语言,但它很稳定,并且你会发如今不少基础需求上,已经有高质量的文件包可用了。
缘由 8:GOFMT,强制代码格式
Gofmt 是一种强大的命令行功能,内建在 Go 的编译器中来规定代码的格式。从功能上看,它相似于 Python 的 autopep8。格式一致很重要,但实际的格式标准并不老是很是重要。Gofmt 用一种官方的形式规格代码,避免了没必要要的讨论。
缘由 9:gRPC 和 Protocol Buffers
Go 语言对 protocol buffers 和 gRPC 有一流的支持。这两个工具能一块儿友好地工做以构建须要经过 RPC 进行通讯的微服务器(microservices)。咱们只须要写一个清单(manifest)就能定义 RPC 调用发生的状况和参数,而后从该清单将自动生成服务器和客户端代码。这样产生代码不只快速,同时网络占用也很是少。
从相同的清单,咱们能够从不一样的语言生成客户端代码,例如 C++、Java、Python 和 Ruby。所以内部通讯的 RESET 端点不会产生分歧,咱们每次也就须要编写几乎相同的客户端和服务器代码。
使用 Go 语言的缺点
缺点 1:缺乏框架
Go 语言没有一个主要的框架,如 Ruby 的 Rails 框架、Python 的 Django 框架或 PHP 的 Laravel。这是 Go 语言社区激烈讨论的问题,由于许多人认为咱们不该该从使用框架开始。在不少案例状况中确实如此,但若是只是但愿构建一个简单的 CRUD API,那么使用 Django/DJRF、Rails Laravel 或 Phoenix 将简单地多。
缺点 2:错误处理
Go 语言经过函数和预期的调用代码简单地返回错误(或返回调用堆栈)而帮助开发者处理编译报错。虽然这种方法是有效的,但很容易丢失错误发生的范围,所以咱们也很难向用户提供有意义的错误信息。错误包(errors package)能够容许咱们添加返回错误的上下文和堆栈追踪而解决该问题。
另外一个问题是咱们可能会忘记处理报错。诸如 errcheck 和 megacheck 等静态分析工具能够避免出现这些失误。虽然这些解决方案十分有效,但可能并非那么正确的方法。
缺点 3:软件包管理
Go 语言的软件包管理绝对不是完美的。默认状况下,它没有办法制定特定版本的依赖库,也没法建立可复写的 builds。相比之下 Python、Node 和 Ruby 都有更好的软件包管理系统。然而经过正确的工具,Go 语言的软件包管理也能够表现得不错。
咱们能够使用 Dep 来管理依赖项,它也能指定特定的软件包版本。除此以外,咱们还能够使用一个名为 VirtualGo 的开源工具,它能轻松地管理 Go 语言编写的多个项目。
这个“火”字看你怎么理解了。
Go在国内更火只是感受上的。好比推文,以及谈论的相关话题较多而已(但能有nodejs多么?),自己中国人口数量就多,按这个衡量的办法去看的话,swift在国内也比在国外火;
实际上Go在国外更火(这里的火是实际的使用状况),对比一下国内和国外使用Go的程度、数量,Go相关的技术大会举办的频率和数量就一目了然了。
Go在国内真正上被全栈使用的就七牛一家,但国外除了docker,coreOS还有不少初创企业。
国内比较有影响力的就一个beego框架,你看看国外的有多少。
去github上搜一下active的Go的project数量,看看Go在国外是否是没人用?我反正在github的trending里面几乎天天都能看到Go的project。hacker news上面有关Go的“xxx writen in Go”的炒做文也不要太多。
这个 dariubs/GoBooks · GitHub 是有人整理的Go相关的书籍,看看是否是国外的书籍比国内的少?8月份K&R中的K也要推出属于Go的圣经了。 另外老有人喜欢说:Google喜欢关闭产品,这玩意儿早晚死掉。惋惜golang是开源项目,关不掉的,CloudFlare那个crypto的patch(Gerrit Code Review)之后可能会进Go的标准库,Godep已经成为事实上的包管理标准,这些都是社区本身搞出来的,和google一毛线关系没有。另外就是最近google本身一些主力产品或者平台在优先支持语言上,Go老是和java,c/c++,python一块儿名列其中,grpc就是一个例子等等。因此,以为Go只是google的一个玩具的人,你的观点能不能站得住脚,本身掂量吧。 个人我的观点是: Go显示已经站住了脚跟(若是是2013年,我仍是不敢说这种话的),找到了属于本身的空间,可是比起那些主流的甚至nodeJS来讲,仍是使用的不够普遍。这个语言人为炒做也罢,一些人认为的google光环也罢,实际使用也罢,总之: 这个语言已经站住脚跟了,能用于而且已经用于生产环境了,接下来几年只会一直呈上升势头。
我的观点:
1 一些真正使用go语言的公司:
这些公司在高速发展的同时,Golang也所以在国内逐渐传播开来。在云计算时代,从国内Go 语言发展和应用来看,七牛算是国内第一家选 Go 语言作服务端的公司。早在2011年,当Go语法还没彻底稳定下来的状况下,七牛就已经选择将Go做为存储服务端的主题语言。关于这点,七牛CEO许式伟谈到:编程哲学的重塑是 Go 语言独树一帜的根本缘由,其它语言仍难以摆脱 OOP 或函数式编程的烙印,只有 Go 彻底放弃了这些,对编程范式从新思考,对热门的面向对象编程提供极度简约但却完备的支持。Go 是互联网时代的C语言,不只会制霸云计算,10 年内将会制霸整个 IT 领域。
2 在中国程序员眼中,谷歌出品必属精品
确实,在互联网世界,在开源世界,Google为咱们贡献了太多太多。
3 创业公司伪装高逼格,伪装geek范儿
The word geek is a slang term originally used to describe eccentric or non-mainstream people; in current use, the word typically connotes an expert or enthusiast or a person obsessed with a hobby or intellectual pursuit, with a general pejorative meaning of a “peculiar person, especially one who is perceived to be overly intellectual, unfashionable, or socially awkward”.
4 docker异常火爆,带动了对go语言的关注
Docker是PaaS供应商dotCloud开源的一个基于LXC 的高级容器引擎,源代码托管在 GitHub 上, 基于Go语言开发并听从Apache 2.0协议开源。
5 go语言自己的一些特性
部署简单
并发性好
性能好
。。。
6《go语言从入门到放弃》一书的火爆
GO语言最初的定位就是互联网时代的C语言,因此,它的基础哲学也来源于C语言,而C语言的成功正是由于它的简单。而简洁的表达方式也会提高程序员的开发效率。
并发性好
几年前,要实现并发编程并非一件容易的事儿,要想完成并发编程要同时了解线程、锁、Semaphore、CPU缓存方式等等,而多核处理器的普及,让编程语言更为注重并发性,而Go语言,能够在一个进程中执行有数以十万计的协程,依旧保持高性能。
应用场景符合将来需求
有人猜想,今年10月GO语言增加率如此之高的缘由之一是:Docker的普及。若是真是如此,那么GO语言将持续如此高的增加率。除此以外,GO语言适用于服务器编程、 分布式系统、网络编程、内存数据库和云平台,而这些领域正是IT技术将来发展的重要方向。
“我为何选择使用Go语言?”
“Go语言能够说是开发效率和运行效率两者的完美融合,天生的并发编程支持。”,苹果核心系统高级工程师、EGO会员、GopherChina组织者、《Go Web编程》做者谢孟军说。
当被问到本身为何如此钟情于使用Go语言,谢孟军谈到了如下几个缘由:
学习曲线
它包含了类C语法、GC内置和工程工具。这一点很是重要,由于Go语言容易学习,因此一个普通的大学生花一个星期就能写出来能够上手的、高性能的应用。在国内你们都追求快,这也是为何国内Go流行的缘由之一。
效率
Go拥有接近C的运行效率和接近PHP的开发效率,这就颇有利的支撑了上面你们追求快速的需求。
出身名门、血统纯正
之因此说Go出身名门,是由于咱们知道Go语言出自Google公司,这个公司在业界的知名度和实力天然不用多说。Google公司汇集了一批牛人,在各类编程语言称雄争霸的局面下推出新的编程语言,天然有它的战略考虑。并且从Go语言的发展态势来看,Google对它这个新的宠儿仍是很看重的,Go天然有一个良好的发展前途。咱们看看Go语言的主要创造者,血统纯正这点就可见端倪了。
自由高效:组合的思想、无侵入式的接口
Go语言能够说是开发效率和运行效率两者的完美融合,天生的并发编程支持。Go语言支持当前全部的编程范式,包括过程式编程、面向对象编程以及函数式编程。程序员们能够各取所需、自由组合、想怎么玩就怎么玩。
强大的标准库
这包括互联网应用、系统编程和网络编程。Go里面的标准库基本上已是很是稳定了,特别是我这里提到的三个,网络层、系统层的库很是实用。
部署方便:二进制文件、Copy部署
我相信这一点是不少人选择Go的最大理由,由于部署太方便了,因此如今也有不少人用Go开发运维程序。
简单的并发
它包含了下降心智的并发和简易的数据同步,我以为这是Go最大的特点。之因此写正确的并发、容错和可扩展的程序如此之难,是由于咱们用了错误的工具和错误的抽象,Go能够说这一块作的至关简单。
稳定性
Go拥有强大的编译检查、严格的编码规范和完整的软件生命周期工具,具备很强的稳定性,稳定压倒一切。那么为何Go相比于其余程序会更稳定呢?这是由于Go提供了软件生命周期(开发、测试、部署、维护等等)的各个环节的工具,如go tool、gofmt、go test。
这里引用知乎里一个同窗对Go评论的话:最开始准备上线的时候其实内心挺忐忑,毕竟一旦出现故障,不只黑锅得本身背,面子也上过不去啊。还好结果蛮漂亮,自上线后没出现过一次突发性BUG,下降运维难度的同时还减小了机器的负载。我相信这也是大多数人用了Go以后的感言。
那么目前Go还存在哪些缺点呢?如下是我本身在项目开发中遇到的一些问题:
Go的Import包不支持版本,有时候升级容易致使项目不可运行,因此须要本身控制相应的版本信息。比较好的现象是从Go 1.5开始Go对此就有重视了并支持Vendor。
Go的goroutine一旦启动后,不一样的goroutine之间切换不是受程序控制,runtime调度的时候须要严谨的逻辑,否则goroutine休眠,过一段时间逻辑结束了却忽然冒出来又执行了,这会致使逻辑出错等状况。这个目前无解,应该属于调度器的优化。
GC延迟有点大,我开发的日志系统伤过一次,同时在并发很大的状况下,处理很大的日志,GC没有那么快,内存回收不给力,后来通过Profile程序改进以后获得了改善。目前来看,GC已经优化的很是好了,给你们看一下Go1.五、Go1.6的GC先后对比图。
图3
图3是Go1.4升级到Go1.5以后的效果,从300ms到了50ms左右。
图4
图4是从Go1.5升级到Go1.6,从40ms到了2ms左右,能够说目前GC基本上不是Go的问题了。
pkg下面的图片处理库不少bug,仍是使用成熟产品好,调用这些成熟库imagemagick的接口比较靠谱。总而言之,从工程的角度上来看,对于大多数后台应用场景,选择Golang是极为明智的选择。 这样能够很轻松的兼顾运行性能、开发效率及维护难度这三大让诸多程序猿欲仙欲死的点。
哪些领域在用Go语言?
“在美国市值前20的企业有超过一半正在使用Go”。不只市值前20的企业,国外不少初创企业,都在使用Go语言。 近年来,Go语言在中国的关注,也异常火爆。几乎每一天,都听到许多人谈论到 Go语言。国外甚至有人,专门写了一篇文章,来分析为何go在中国如此火:Why is Golang popular in China?: http://herman.asia/why-is-go-popular-in-china
目前,Go语言被普遍应用于各类领域。
软件开发工具
几乎全部这几年出现的 软件开发 工具都已经被用 Go语言 语言改写了。我以为这恐怕预示着什么。一般,相对于通常的开发小组,小公司的运维小组收到的监管不多。只要是能工做的工具,他们通常就会去用,而不须要获 得谁的批准。对他们来讲 Go语言 语言工做的很是棒,这是一门静态类型和编译型的语言(无需安装须要上千个依赖的运行库),并且 Go语言 的运行库也不大,也不用动不动就须要 100-300M的磁盘空间(看看 ruby、jvm 吧)。
比特币
许多DeferPanic 上的用户都与比特币/虚拟货币有关。这并不是巧合,整个生态系统的共同点是使用Go语言。
无论你听到过什么,比特币都尚未死掉。不少用例传统上没想到过的,可是实际上已经有了很大的成功。咱们的这些用户须要有高性能和更好的数据安全性的保证,Go语言在这方面显然是很好的选择。
容器技术
有趣的是和那些科技人士交谈后发现他们竟然不知道今天全部容器技术都是 Go语言 写的,不是 99%,也不是 95%-100%。
全部今天在使用的容器软件都是 Go语言 写的。
市场营销人员应该开始用 Go语言 原生来替换云原生。
咱们能够强调这是有多大(的市场)?即便你不相信容器的炒做,认为这是一个庞式骗局。当你考虑到全部公司使用 Go语言 的人数,而且将来几年大公司使用 Go语言 人数巨大。问你从世界财富五百强的首席信息官那据说他们将要检修他们系统,你不得不意识到这订单很大。这不是他们看轻这件事,相反,他们也不会轻易的从中 走开,由于这是一个巨大的对时间,金钱以及过程的投资。
微服务
微服务在过去的几年风靡一时,很多分析师忽略了它们的价值,由于他们并非搞技术的。当你用maven下载了半个互联网,同时启动要占用 800M 虚拟内存,或者当你运行一个 RoR 的应用的时候占用了 200M,这和 Go语言 平均 5-20M 的运行时想比真是相差巨大。这种差距能够马上转换到帐单上,当你公司每月少给 25-30 美金在 AWS 上就显而易见了。随着这种激烈的趋势下去,咱们会看到愈来愈多的公司由于上述理由采用这种模式,而且你能够打赌即将迎来 Go语言 的时代。
商业应用
当谈及到一些知道 Docker 的人颇有趣,他们甚至会去投资它在他们并不知道这个是由一个他们从未听过的 Go语言 编写而成的以前。
历来自 Battery 的 Adrian (也是来自 Netflix)今年在他与公司的交流中曾经数次说到 Go语言:
“大概四分之三的新东西是用 Go语言 写的 @golang” – 十二月十四号
L 接着他又提到 “几乎全部新的、有趣的东西都是用 Go语言 写的”.
在他的行业里面他可能有更好的眼光,由于他参加过不少会议,并如此的接地气。来自 Mayfield 的 Robin Vasan 甚至在今年的 goper 大会上进行了一次演讲在 VC 工做,而且精通 Go语言 的 Jerry Chen 曾经出席大会并有良好表现。
今年2月,Go 团队发布了 Go 1.8 ,编译时间比 Go 1.7 提升了约 15%。
技术发展进行时,技术大会怎么能落下?
Gopher2017大会,StuQ独家直播!
这个4月 ,中国最权威和最实力干货的 Go 大会——Gopher China 大会来啦!!!致力于为中国广大的 Gopher 提供最好的技术大会,Gopher China 每一年都会汇集一批大规模应用 Go 的示范企业分享经验。
4.15 - 4.16,国内最大最专业的Go大会—GopherChina大会,将在魔都上海举行。本次大会邀请了空前强大的导师阵容,呈现 Go 在微服务、大数据、金融、Go 内核等多个最前沿主题的技术演讲。
他们分别是Google Cloud 工程师Francesc Campoy、哔哩哔哩的技术总监毛剑、华为开源技术专家马全1、阿里云工程师聪心、360 工程师郭军、有赞科技技术专家李文、VMWare中国研发中心云原生应用首席架构师张海宁、七牛大数据开发高级工程师孙建波……
想知道在此次GopherChina大会上,技术大咖们会有哪些精彩观点?想知道微服务、大数据、金融、Go 内核的最前沿趋势?
做者:庄晓立(Liigo)
日期:2014年3月
原创连接:http://blog.csdn.net/liigo/article/details/23699459
转载请注明出处:http://blog.csdn.net/liigo
有好几回,当我想起来的时候,老是会问本身:我为何要放弃Go语言?这个决定是正确的吗?是明智和理性的吗?其实我一直在认真思考这个问题。
开门见山地说,我当初放弃Go语言(golang),就是由于两个“不爽”:第一,对Go语言自己不爽;第二,对Go语言社区里的某些人不爽。毫无疑问,这是很是主观的结论。可是我有足够详实的客观的论据,用以支撑这个看似主观的结论。
文末附有本文更新日志。
先说说个人经历吧,以免被平白无故地看成Go语言的低级黑。
2009年末,Go语言(golang)第一个公开版本发布,笼罩着“Google公司制造”的光环,吸引了许多慕名而来的尝鲜者,我(Liigo)也身居其中,笼统的看了一些Go语言的资料,学习了基础的教程,因对其语法中的分号和花括号不满,很快就遗忘掉了,没拿它当一回事。
两年以后,2011年末,Go语言发布1.0的计划被提上日程,相关的报道又多起来,我再次关注它,[从新评估][1]以后决定深刻参与Go语言。我订阅了其users、nuts、dev、commits等官方邮件组,坚持天天阅读其中的电子邮件,以及开发者提交的每一次源代码更新,给Go提交了许多改进意见,甚至包括[修改Go语言编译器源代码][2]直接参与开发任务。如此持续了数月时间。
到2012年初,Go 1.0发布,语言和标准库都已经基本定型,不可能再有大幅改进,我对Go语言未能在1.0定型以前更上一个台阶、实现自我突破,甚至带着诸多明显缺陷走向1.0,感到很是失望,于是逐渐疏远了它(因此Go 1.0以后的事情我不多关心)。后来看到即将发布的Go 1.1的Release Note,发现语言层面没有太大改变,只是在库和工具层面有所修补和改进,感到它尚在幼年就失去成长的动力,愈加失望。外加Go语言社区里的某些人,其中也包括Google公司负责开发Go语言的某些人,其态度、言行,让我极度厌恶,促使我决绝地离弃Go语言。
在上一个10年,我(Liigo)在我所属的公司里,深度参与了两个编程语言项目的开发。我想,对于如何判断某个编程语言的优劣,或者说至少对于如何判断某个编程语言是否适合于我本身,我应该仍是有一点发言权的。
[1]: https://plus.google.com/+LiigoZhuang/posts/CpRNPeDXUDW
[2]: http://blog.csdn.net/liigo/article/details/7467309
Go语言有不少让我不爽之处,这里列出我如今还能记起的其中一部分,排名基本上不分前后。读者们耐心地看完以后,还能淡定地说一句“我不在意”吗?
关于对花括号的摆放,在C语言、C++、Java、C#等社区中,十余年来存在持续争议,从未造成一致意见。在我看来,这原本就是主观倾向很重的抉择,不违反原则不涉及是非的状况下,不该该搞一刀切,让程序员或团队本身选择就足够了。编程语言自己强行限制,把本身的喜爱强加给别人,得不偿失。不管倾向于其中任意一种,必然得罪与其对立的一群人。虽然我如今已经习惯了把左花括号放在行尾,但一想到被禁止其余选择,就感到十分不爽。Go语言这这个问题上,没有作到“团结一切能够团结的力量”不说,还有意给本身树敌,太失败了。
对Go语言自己而言,行尾的分号是能够省略的。可是在其编译器(gc)的实现中,为了方便编译器开发者,却在词法分析阶段强行添加了行尾的分号,反过来又影响到语言规范,对“怎样添加分号”作出特殊规定。这种变态作法前无古人。在左花括号被意外放到下一行行首的状况下,它自动在上一行行尾添加的分号,会致使莫名其妙的编译错误(Go 1.0以前),连它本身都解释不明白。若是实在处理很差分号,干脆不要省略分号得了;或者,Scala和JavaScript的编译器是开源的,跟它们学学怎么处理省略行尾分号能够吗?
程序员是人不是神,编码过程当中免不了由于大意或疏忽犯一些错。其中有一些,是你们集体性的很容易就中招的错误(Go语言里的例子我暂时想不起来,C++里的例子有“基类析构函数不是虚函数”)。这时候编译器应该站出来,多作一些检查、约束、核对性工做,尽可能阻止常规错误的发生,尽可能不让有潜在错误的代码编译经过,必要时给出一些警告或提示,让程序员留意。编译器不就是机器么,不就是应该多作脏活累活杂活、减小人的心智负担么?编译器多作一项检查,可能会避免数十万程序员从此多年内无数次犯一样的错误,节省的时间不可胜数,这是功德无量的好事。可是Go编译器的做者们可不这么想,他们不肯意本身多花几个小时给编译器增长新功能,以为那是亏本,反而减慢了编译速度。他们以影响编译速度为由,拒绝了不少对编译器改进的要求。典型的因噎废食。强调编译速度当然值得赞扬,但若是所以放弃应有的功能,我不同意。
在Go语言中处理错误的基本模式是:函数一般返回多个值,其中最后一个值是error类型,用于表示错误类型极其描述;调用者每次调用完一个函数,都须要检查这个error并进行相应的错误处理:if err != nil { /*这种代码写多了不想吐么*/ }。此模式跟C语言那种很原始的错误处理相好比出一辙,并没有实质性改进。实际应用中很容易造成多层嵌套的if else语句,能够想想这个编码场景:先判断文件是否存在,若是存在则打开文件,若是打开成功则读取文件,若是读取成功再写入一段数据,最后关闭文件,别忘了还要处理每一步骤中出现错误的状况,这代码写出来得有多变态、多丑陋?实践中广泛的作法是,判断操做出错后提早return,以免多层花括号嵌套,但这么作的后果是,许多错误处理代码被放在前面突出的位置,常规的处理逻辑反而被掩埋到后面去了,代码可读性极差。并且,error对象的标准接口只能返回一个错误文本,有时候调用者为了区分不一样的错误类型,甚至须要解析该文本。除此以外,你只能手工强制转换error类型到特定子类型(静态类型的优点没了)。至于panic - recover机制,致命的缺陷是不能跨越库的边界使用,注定是一个半成品,最多只能在本身的pkg里面玩一玩。Java的异常处理虽然也有自身的问题(好比Checked Exceptions),但整体上仍是比Go的错误处理高明不少。
在Go 1.0前夕,其垃圾回收器在32位环境下有内存泄漏,一直拖着不愿改进,这且不说。Go语言垃圾回收器真正致命的缺陷是,会致使整个进程不可预知的间歇性停顿(Stop the World)。像某些大型后台服务程序,如游戏服务器、APP容器等,因为占用内存巨大,其内存对象数量极多,GC完成一次回收周期,可能须要数秒甚至更长时间,这段时间内,整个服务进程是阻塞的、停顿的,在外界看来就是服务中断、无响应,再牛逼的并发机制到了这里通通失效。垃圾回收器按期启动,每次启动就致使短暂的服务中断,这样下去,还有人敢用吗?这但是后台服务器进程,是Go语言的重点应用领域。以上现象可不是我假设出来的,而是事实存在的现实问题,受其严重困扰的也不是一家两家了(2013年末ECUG Con 2013,京东的刘奇提到了Go语言的GC、defer、标准库实现是性能杀手,最大的痛苦是GC;美团的沈锋也提到Go语言的GC致使后台服务间隔性停顿是最大的问题。更早的网络游戏仙侠道开发团队也曾受Go垃圾回收的沉重打击)。在实践中,你必须努力减小进程中的对象数量,以便把GC致使的间歇性停顿控制在可接受范围内。除此以外你别无选择(难道你还想本身更换GC算法、甚至砍掉GC?那仍是Go语言吗?)。跳出圈外,我近期一直在思考,必定须要垃圾回收器吗?没有垃圾回收器就必定是历史的倒退吗?(可能会新写一篇博客文章专题探讨。)
2016年3月3日Liigo补记:直到2015年末,Go 1.5新GC发布后数月,仍获知有大陆圈内知名团队由于GC的缘由考虑换掉Go语言,很有感触。当软件系统逐步发展到更庞大更复杂的时候,Go语言的垃圾回收器(GC)就变成了指不定啥时候会出现的拦路虎,让人进退两难。进,暂时没有确切有效的技术手段对付响应延迟和内存暴涨;退,多年开发付出的心血付之东流损失惨重。语言选型以前多作调查分析,若是必定要用Go语言开发,控制系统规模和复杂度,避开底层的核心业务,多是比较明智的选择。
Go编译器不容许存在被未被使用的变量和多余的import,若是存在,必然致使编译错误。可是现实状况是,在代码编写、重构、调试过程当中,例如,临时性的注释掉一行代码,很容易就会致使同时出现未使用的变量和多余的import,直接编译错误了,你必须相应的把变量定义注释掉,再翻页回到文件首部把多余的import也注释掉,……等事情办完了,想把刚才注释的代码找回来,又要好几个麻烦的步骤。还有一个让人蛋疼的问题,编写数据库相关的代码时,若是你import某数据库驱动的pkg,它编译给你报错,说不须要import这个未被使用的pkg;但若是你听信编译器的话删掉该import,编译是经过了,运行时必然报错,说找不到数据库驱动;你看看程序员被折腾的两边不是人,最后不得不请出大神:`import _`。对待这种问题,一个比较好的解决方案是,视其为编译警告而非编译错误。可是Go语言开发者很执拗,不允许这种折中方案。
建立对象的方式,调用new函数、调用make函数、调用New方法、使用花括号语法直接初始化结构体,你选哪种?很差选择,由于没有一个固定的模式。从实践中看,若是要建立一个语言内置类型(如channel、map)的对象,一般用make函数建立;若是要建立标准库或第三方库定义的类型的对象,首先要去文档里找一下有没有New方法,若是有就最好调用New方法建立对象,若是没有New方法,则退而求其次,用初始化结构体的方式建立其对象。这个过程颇为周折,不像C++、Java、C#那样直接new就好了。
没有构造函数还好说,毕竟还有自定义的New方法,大体也算是构造函数了。没有析构函数就比较难受了,无法实现RAII。额外的人工处理资源清理工做,无疑加剧了程序员的心智负担。没人性啊,还嫌咱们程序员加班还少吗?C++里有析构函数,Java里虽然没有析构函数可是有人家finally语句啊,Go呢,什么都没有。没错,你有个defer,但是那个defer问题更大,详见下文吧。
Go语言设计defer语句的出发点是好的,把释放资源的“代码”放在靠近建立资源的地方,但把释放资源的“动做”推迟(defer)到函数返回前执行。遗憾的是其执行时机的设置彷佛有些不甚合理。设想有一个须要长期运行的函数,其中有无限循环语句,在循环体内不断的建立资源(或分配内存),并用defer语句确保释放。因为函数一直运行没有返回,全部defer语句都得不到执行,循环过程当中建立的大量短暂性资源一直积累着,得不到回收。并且,系统为了存储defer列表还要额外占用资源,也是持续增长的。这样下去,过不了多久,整个系统就要由于资源耗尽而崩溃。像这类长期运行的函数,http.ListenAndServe()就是典型的例子。在Go语言重点应用领域,能够说几乎每个后台服务程序都必然有这么一类函数,每每还都是程序的核心部分。若是程序员不当心在这些函数中使用了defer语句,能够说后患无穷。若是语言设计者把defer的语义设定为在所属代码块结束时(而非函数返回时)执行,是否是更好一点呢?但是Go 1.0早已发布定型,为了保持向后兼容性,已经不可能改变了。当心使用defer语句!一不当心就中招。
for in、make、range、channel、map等都仅支持语言内置类型,不支持用户定义的类型(?)。用户定义的类型无法支持for in循环,用户不能编写像make、range那样“参数类型和个数”甚至“返回值类型和个数”均可变的函数,不能编写像channel、map那样相似泛型的数据类型。语言内置的那些东西,到处充斥着斧凿的痕迹。这体现了语言设计的局限性、封闭性、不完善,可扩展性差,像是新手做品——且不论其设计者和实现者如何权威。延伸阅读:Go语言是30年前的陈旧设计思想,用户定义的东西几乎都是二等公民(Tikhon Jelvis)。
没有泛型的话,List、Set、Tree这些常见的基础性数据类型的接口就只能很丑陋:放进去的对象是一个具体的类型,取出来以后成了无类型的interface{}
(能够视为全部类型的基础类型),还得强制类型转换以后才能继续使用,使人无语。Go语言缺乏min、max这类函数,求数值绝对值的函数abs只接收/返回双精度小数类型,排序接口只能借助sort.Interface无奈的回避了被比较对象的类型,等等等等,都是没有泛型致使的结果。没有泛型,接口很难优雅起来。Go开发者没有明确拒绝泛型,只是说尚未找到很好的方法实现泛型(能不能学学已经开源的语言呀)。现实是,Go 1.0已经定型,泛型尚未,那些丑陋的接口为了保持向后兼容必须长期存在着。延伸阅读:HN网友抱怨Go没有泛型。
这一条一般是被看成Go语言的优势来宣传的。可是也有人不赞同,好比我。若是一个类型用Go语言的方式默默的实现了某个接口,使用者和代码维护者都很难发现这一点(除非仔细核对该类型的每个方法的函数签名,并跟全部可能的接口定义相互对照),天然也想不到与该接口有关的应用,显得十分隐晦,不直观。支持者可能会辩解说,我能够在文档中注明它实现了哪些接口。问题是,写在文档中,还不如直接写到类型定义上呢,至少还能获得编译器的静态类型检查。缺乏了编译器的支持,当接口类型的函数签名被改变时,当实现该接口的类型方法被无心中改变时,实现者可能很难意识到,该类型实现该接口的隐含约束事实上已经被打破了。又有人辩解说,我能够经过单元测试确保类型正确实现了接口呀。我想说的是,明明能够经过明确声明实现接口,享受编译器提供的类型检查,你却要本身找麻烦,去写本来多余的单元测试,找虐很爽吗?Go语言的这种作法,除了减小一些对接口所在库的依赖以外,没有其余好处,得不偿失。延伸阅读:为何我不喜欢Go语言式的接口(老赵)。
Go语言里面的if语句,其条件表达式不须要用小括号扩起来,这被做为“代码比较简洁”的证据来宣传。但是,你省掉了小括号,却不能省掉大括号啊,一条完整的if语句至少还得三行吧,人家C、C++、Java均可以在一行以内搞定的(能够省掉花括号)。人家还有x?a:b
表达式呢,也是一行搞定,你Go语言用if else写至少得五行吧?哪里简洁了?
记得当年我写了一个很简单的程序,把全部系统环境变量的名称和值输出到控制台,核心代码也就那么三五行,结果编译出来把我吓坏了:EXE文件的大小超过4MB。若是是C语言写的一样功能的程序,0.04MB都是多的。我把这个信息反馈到官方社区,结果人家不在意。是,我知道如今的硬盘容量都数百GB、上TB了……可您这种优化程度……怎么让我相信您在其余地方也能作到不错呢。(再次强调一遍,我全部的经验和数据都来自Go 1.0发布前夕。)
静态编译的程序固然是很好的,没有额外的运行时依赖,部署时很方便。可是以前咱们说了,静态编译的文件尺寸很大。若是一个软件系统由多个可执行程序构成,累加起来就很可观。若是用动态编译,发布时带同一套动态库,能够节省不少容量。更关键的是,动态库能够运行时加载和卸载,这是静态库作不到的。还有那些LGPL等协议的第三方C库受版权限制是不容许静态编译的。至于动态库的版本管理难题,能够经过给动态库内的全部符号添加版本号解决。不管如何,应该给予程序员选择权,让他们本身决定使用静态库仍是动态库。一刀切的拒绝动态编译是不合适的。
interface XXX{}
struct YYY{}
不是更简洁吗?前面加上type
关键字显得罗嗦。if a != b { t.Fatal(...) }
。上面列出的是我目前还能想到的对Go语言的不爽之处,毕竟时间过去两年多,还有一些早就遗忘了。其中一部分当然是小不爽,可能忍一忍就过去了,可是不少不爽积累起来,总会时不时地让人难受,时间久了有自虐的感受。程序员的工做生活原本就够枯燥的,何须呢。
必需要说的是,对于其中大多数不爽之处,我(Liigo)都曾经试图改变过它们:在Go 1.0版本发布以前,我在其官方邮件组提过不少意见和建议(甚至包括提交代码CL),极力力排众议,能够说付出很大努力,目的就是但愿定型后的Go语言是一个相对完善的、没有明显缺陷的编程语言。结果是使人失望的,我人微言轻、势单力薄,不可能影响整个语言的发展走向。1.0以前,最佳的否认自我、超越自个人机会,就这么遗憾地错过了。我最终发现,不少时候不是技术问题,而是技术人员的问题。
这里提到的“某些人”主要是两类:1、负责专职开发Go语言的Google公司员工;2、Go语言的推崇者和脑残粉丝。我跟这两类人打过不少交道,不胜其烦。再次强调一遍,我指的是“某些”人,而不是全部人,请不要对号入座。
Google公司内部负责专职开发Go语言的核心开发组某些成员,他们倾向于闭门造车,执拗己见,对第三方提出的建议不重视。他们经常挂在嘴边的口头禅是:现有的作法很好、不须要那个功能、咱们开发Go语言是给Google本身用的、Google不须要那个功能、若是你必定要改请fork以后本身改、别干提意见请提交代码。不少言行都是“反开源”的。经过一些具体的例子,还能更形象的看清这一层。就留下做为课后做业吧。
我最不能接受的就是他们对1.0版本的散漫处理。那时候Go还没到1.0,初出茅庐的小学生,有很大的改进空间,是全面翻新的最佳时机,彼时不改更待什么时候?1.0是打地基的版本,基础不牢靠,等1.0定型以后,到处受到向后兼容性的牵制,束手缚脚,每前进一步都阻力重重。急于发布1.0,过早定型,留下诸多遗憾,彰显了开发者的功利性强,在技术上不追求尽善尽美。
Go语言的核心开发成员,他们平常的开发工做是使用C语言——Go语言的编译器和运行时库,包括语言核心数据结构和算法map、channel、scheduler,都是C开发的——真正用本身开发的Go语言进行实际的大型应用开发的机会并很少。虽然标准库是用Go语言本身写的,但他们却没有大范围使用标准库的经历。实际上,他们缺乏使用Go语言的实战开发经验,每每不知道处于开发第一线的用户真正须要什么,没法作到设身处地为程序员着想。缺乏使用Go语言的亲身经历,也意味着他们不能在平常开发中,及时发现和改进Go语言的不足。这也是他们每每自我感受良好的缘由。(2016年5月15日补记:2015年8月Go 1.5版本以后再也不使用C语言开发。)
Go语言社区里,有一大批Go语言的推崇者和脑残粉丝,他们知足于现状,不思进取,到处维护心中的“神”,容不得批评意见,不支持对语言的改进要求。当年我对Go语言的不少批评和改进意见,极少获得他们的支持,他们不但不支持还给予打击,我就纳闷了,他们难道不但愿Go语言更完善、更优秀吗?我后来才意识到,他们跟乔帮主的苹果脑残粉丝们,言行一脉相承,具备极端宗教倾向,神化主子、打击异己真是竭尽全力呀。简简单单的技术问题,就能被他们上升到意识形态之争。现实的例子是蛮多的,有兴趣的到网上去找吧。正是由于他们的存在,致使更多理智、清醒的Go语言用户没法真正融入整个社区。
若是一个项目、团队、社区,处处充斥着赞美、孤芳自赏、自我知足、不思进取,排斥不一样意见,拒绝接纳新方案,我想不到它还有什么前进的动力。逆水行舟,是不进反退的。
2016年5月15日补记:@netroby:“Golang社区的神经病和执拗,我深有体会。我曾经发过Issue,请求Golang官方,能为doc加上高亮,这样浏览器阅读文档的时候,能快速阅读代码参考。可是被各类拒绝. 他们的理由是不少开发者不喜欢高亮。” https://github.com/golang/go/issues/13178
2016年5月15日补记:C++天才人物、D语言联合创始人Andrei Alexandrescu:“Go所走的路线在一些问题上持有极其强硬和死板态度,这些问题有大有小。在比较大的方面,泛型编程被严格控制,甚至贬低到只有"N"个字;有关泛型编程的讨论都是试图去劝阻任何有意义的尝试,这已经足够让人以为耻辱。从长远来看,技术问题的政治化是一种极其有害的模式,因此但愿Go社区可以找到修正它的方法。” http://www.csdn.net/article/2015-12-20/2826517
我始终坚持一个很有辩证法意味的哲学观点:在更好的替代品出现以前,现有的就是最好的。失望是没有用的,抱怨是没有用的,要么接受,要么逃离。我曾经努力尝试过接受Go语言,失败以后,注定要逃离。发现更好的替代品以后,无疑加速了逃离过程。还有比Go语言更好的替代品吗?固然有。做为一个屌丝程序员,我应该告诉你它是什么,可是我不说。如今还不是时候。我如今不想把这两门编程语言对立起来,引起另外一场潜在的语言战争。这不是此文的本意。若是你非要从现有信息中推测它是什么,那彻底是你本身的事。若是你原意等,它或许很快会浮出水面,也未可知。
我不原意被别人表明,也不肯意表明别人。这篇文章写的是我,一个叫Liigo的80后屌丝程序员,本身的观点。你彻底能够主观地认为它是主观的,也彻底能够客观地觉得它是客观的,不管如何,那是你的观点。
这篇文字是从记忆里收拾出来的。有些细节虽可考,而不值得考。——我早已逃离,不肯再回到当年的场景。文中涉及的某些细节,可能会由于些许误差,影响其准确性;也可能会由于缺乏出处,影响其客观性。若是有人较真,非要去核实,我相信那些东西应该还在那里。
Go语言也非上文所述一无可取,它固然有它的优点和特点。读者们判断一件事物,应该是优劣并陈,作综合分析,不能单听我一家负面之言。可是它的那些不爽之处,始终让我不爽,且不能从其优秀处得以彻底中和,这是我不得不放弃它的缘由。
go教程: