go语言,是用在服务端的。
- 部署简单。Go 编译生成的是一个静态可执行文件,除了 glibc 外没有其他外部依赖。这让部署变得异常方便:目标机器上只需要一个基础的系统和必要的管理、监控工具,完全不需要操心应用所需的各种包、库的依赖关系,大大减轻了维护的负担。这和 Python 有着巨大的区别。由于历史的原因,Python 的部署工具生态相当混乱【比如 setuptools, distutils, pip, buildout 的不同适用场合以及兼容性问题】。官方 PyPI 源又经常出问题,需要搭建私有镜像,而维护这个镜像又要花费不少时间和精力。
- 并发性好。Goroutine 和 channel 使得编写高并发的服务端软件变得相当容易,很多情况下完全不需要考虑锁机制以及由此带来的各种问题。单个 Go 应用也能有效的利用多个 CPU 核,并行执行的性能好。这和 Python 也是天壤之比。多线程和多进程的服务端程序编写起来并不简单,而且由于全局锁 GIL 的原因,多线程的 Python 程序并不能有效利用多核,只能用多进程的方式部署;如果用标准库里的 multiprocessing 包又会对监控和管理造成不少的挑战【我们用的 supervisor 管理进程,对 fork 支持不好】。部署 Python 应用的时候通常是每个 CPU 核部署一个应用,这会造成不少资源的浪费,比如假设某个 Python 应用启动后需要占用 100MB 内存,而服务器有 32 个 CPU 核,那么留一个核给系统、运行 31 个应用副本就要浪费 3GB 的内存资源。
- 良好的语言设计。从学术的角度讲 Go 语言其实非常平庸,不支持许多高级的语言特性;但从工程的角度讲,Go 的设计是非常优秀的:规范足够简单灵活,有其他语言基础的程序员都能迅速上手。更重要的是 Go 自带完善的工具链,大大提高了团队协作的一致性。比如 gofmt 自动排版 Go 代码,很大程度上杜绝了不同人写的代码排版风格不一致的问题。把编辑器配置成在编辑存档的时候自动运行 gofmt,这样在编写代码的时候可以随意摆放位置,存档的时候自动变成正确排版的代码。此外还有 gofix, govet 等非常有用的工具。
- 执行性能好。虽然不如 C 和 Java,但通常比原生 Python 应用还是高一个数量级的,适合编写一些瓶颈业务。内存占用也非常省。
在接触Golang以前,我用C/C++、Lua及Python作为主要开发语言。
C/C++的问题:
- 开发效率低,对开发者要求高
- libc只向后兼容,运维难度偏大
Lua/Python的问题:
- 动态语言,缺少编译过程,低级错误频出
- 缺少有效的性能分析及调试工具
当时刚完成了nginx WAF模块的开发工作,便开始着手搭建WAF的后台管理系统。 由于之前同事都用的fluentd作为日志收集组件,为保持基础组件的一致性,我也选择了fluentd。 即最终架构为fluentd->mongodb->mysql,再基于mysql做前端数据展示。 后来被坑了许多次,就决定用Go重写fluentd以解决下面几个问题:
- fluentd在ubuntu 9.04偶尔会出现假死,导致数据丢失
- fluentd难以接入公司现有的包发布系统,导致运维难度极大
- mongodb采用mmap实现,数据量大时占用内存过高
事实上,这两个项目都是为了解决上面提到的问题。 说起来也许你不信,这两个套代码是我在业余时间完成的,也就是说这根本不算在KPI之内。 其实一开始我也没想到能够这么快就写得七七八八,毕竟是现学现用啊。 但实际情况就是,我花了一周时间写完httpmq,一个月多时间就写好了gofluent……当然,这两个项目还有很多不完善的地方。目前就日志收集方案来说,我更推荐elastic/logstash-forwarder · GitHub和elastic/logstash · GitHub配合使用。
为什么选择Golang
那么,为什么我会选择Golang呢?其实我在做出这个选择之前已经花了大量时间做过详尽调研。 国外如Google、AWS、Cloudflare、CoreOS等,国内如七牛、阿里等都已经开始大规模使用Golang开发其云计算相关产品。 跟着世界级巨人的脚步应该不至于走错方向,而且在学习Golang的过程中,我也渐渐被其背后的设计哲学所折服。
另外,云风博客中曾说过这样一句话:
我发现我花了四年时间锤炼自己用 C 语言构建系统的能力,试图找到一个规范,可以更好的编写软件。结果发现只是对 Go 的模仿。缺乏语言层面的支持,只能是一个拙劣的模仿。
以下则是我对Golang的浅薄理解:
- 有C基础,学Golang非常轻松
- 同步方式轻松实现高并发
- 代码简洁,格式统一,阅读方便
- 性能强劲的同时,开发效率又不差于Python等动态语言
最开始准备上线的时候其实心里挺忐忑,毕竟一旦出现故障,不仅黑锅得自己背,面子也上过不去啊。 还好结果蛮漂亮,自上线后没出现过一次突发性BUG,降低运维难度的同时还减少了机器的负载。
总而言之,从工程的角度上来看,对于大多数后台应用场景,选择Golang是极为明智的选择。 这样可以很轻松的兼顾运行性能、开发效率及维护难度这三大让诸多程序猿欲仙欲死的奇点。
1、Go有什么优势
- 可直接编译成机器码,不依赖其他库,glibc的版本有一定要求,部署就是扔一个文件上去就完成了。
- 静态类型语言,但是有动态语言的感觉,静态类型的语言就是可以在编译的时候检查出来隐藏的大多数问题,动态语言的感觉就是有很多的包可以使用,写起来的效率很高。
- 语言层面支持并发,这个就是Go最大的特色,天生的支持并发,我曾经说过一句话,天生的基因和整容是有区别的,大家一样美丽,但是你喜欢整容的还是天生基因的美丽呢?Go就是基因里面支持的并发,可以充分的利用多核,很容易的使用并发。
- 内置runtime,支持垃圾回收,这属于动态语言的特性之一吧,虽然目前来说GC不算完美,但是足以应付我们所能遇到的大多数情况,特别是Go1.1之后的GC。
- 简单易学,Go语言的作者都有C的基因,那么Go自然而然就有了C的基因,那么Go关键字是25个,但是表达能力很强大,几乎支持大多数你在其他语言见过的特性:继承、重载、对象等。
- 丰富的标准库,Go目前已经内置了大量的库,特别是网络库非常强大,我最爱的也是这部分。
- 内置强大的工具,Go语言里面内置了很多工具链,最好的应该是gofmt工具,自动化格式化代码,能够让团队review变得如此的简单,代码格式一模一样,想不一样都很困难。
- 跨平台编译,如果你写的Go代码不包含cgo,那么就可以做到window系统编译linux的应用,如何做到的呢?Go引用了plan9的代码,这就是不依赖系统的信息。
- 内嵌C支持,前面说了作者是C的作者,所以Go里面也可以直接包含c代码,利用现有的丰富的C库。
- 服务器编程,以前你如果使用C或者C++做的那些事情,用Go来做很合适,例如处理日志、数据打包、虚拟机处理、文件系统等。
- 分布式系统,数据库代理器等
- 网络编程,这一块目前应用最广,包括Web应用、API应用、下载应用、
- 内存数据库,前一段时间google开发的groupcache,couchbase的部分组建
- 云平台,目前国外很多云平台在采用Go开发,CloudFoundy的部分组建,前VMare的技术总监自己出来搞的apcera云平台。
nsq:bitly开源的消息队列系统,性能非常高,目前他们每天处理数十亿条的消息
docker:基于lxc的一个虚拟打包工具,能够实现PAAS平台的组建。
packer:用来生成不同平台的镜像文件,例如VM、vbox、AWS等,作者是vagrant的作者
skynet:分布式调度框架
Doozer:分布式同步工具,类似ZooKeeper
Heka:mazila开源的日志处理系统
cbfs:couchbase开源的分布式文件系统
tsuru:开源的PAAS平台,和SAE实现的功能一模一样
groupcache:memcahe作者写的用于Google下载系统的缓存系统
god:类似redis的缓存系统,但是支持分布式和扩展性
gor:网络流量抓包和重放工具
以下是一些公司,只是一小部分:
- http://Apcera.com
- http://Stathat.com
- Juju at Canonical/Ubuntu, presentation
- http://Beachfront.iO at Beachfront Media
- CloudFlare
- Soundcloud
- Mozilla
- Disqus
- http://Bit.ly
- Heroku
- youtube
GoUsers - go-wiki - A list of organizations that use Go.
4、Go还存在的缺点
以下缺点是我自己在项目开发中遇到的一些问题:
- Go的import包不支持版本,有时候升级容易导致项目不可运行,所以需要自己控制相应的版本信息
- Go的goroutine一旦启动之后,不同的goroutine之间切换不是受程序控制,runtime调度的时候,需要严谨的逻辑,不然goroutine休眠,过一段时间逻辑结束了,突然冒出来又执行了,会导致逻辑出错等情况。
- GC延迟有点大,我开发的日志系统伤过一次,同时并发很大的情况下,处理很大的日志,GC没有那么快,内存回收不给力,后来经过profile程序改进之后得到了改善。
- pkg下面的图片处理库很多bug,还是使用成熟产品好,调用这些成熟库imagemagick的接口比较靠谱
最后还是建议大家学习Go,这门语言真的值得大家好好学习,因为它可以做从底层到前端的任何工作。
学习Go的话欢迎大家通过我写的书来学习,我已经开源在github:
astaxie/build-web-application-with-golang · GitHub
还有如果你用来做API开发或者网络开发,那么我做的开源框架beego也许适合你,可以适当的来学习一下:
astaxie/beego · GitHub
交流群:148647580
py,rb这些需要运行环境,而且速度和编译语言不在统一数量级别。当然go也没有需要虚拟机语言的优势。这点没有重叠。至于重叠的地方,就因人而异了。
http://m.csdn.net/article/2012-07-05/2807113-less-is-exponentially-more
回想2007年9月的时候,我正在为Google庞大的C++程序做一些比较琐碎但是核心的工作(对,就是你们都用过的那个!),我工作在Google庞大的分布式编译集群上都需要花45分钟。之后有几个C++标准委员会的Google员工为我们做了个演讲,他们给我们介绍了下C++0x(现在被叫做C++11)里会有什么新东西。
在那一个小时的演讲中,我们大概听到了约35种计划中的新特性。当然实际上还有更多,但是在那次演讲中我们只听到了35种左右。有的特性比较小,当然演讲中所提到的任何一种特性都可以称得上标志性的:有的比较精妙,但是很难理解,像右值引用(RValue Reference);其它的很有C++的特色,例如variadic模板;还有一些只是一些相当疯狂的,一如用户定义文字(user-defined literal)。
这时候,我问了自己一个问题:C++委员会真的认为C++的特性还不够多?当然,不同于Ron的玩笑,简化这门语言必是一门更大的成就!也许这很可笑,但是请把这个想法记在心里。
在编译结束之前,我们说服了Ken,决定一起做一些事情。我们再也不想用C++了,同时也很希望能在写Google的代码时能用到并行性特性。
它的优势:
- 良好的性能
- 并发支持良好,并且可以很好的利用多核心
- 简单,容易上手使用
我们项目组已经抛弃C++全力使用golang了. 最大的优点: 招人方便, 只要是会一点C语言的, 都可以现学, 2~3天可以贡献代码
隔壁项目组对golang的开发效率和运行效率有目共睹, 测试已经用上了golang. 已经准备下个项目跃跃欲试
首先,当我需要一个通用链表的时候,在Go里面会大致写成如下的样子:
type LinkedList struct {
value interface{}
next *LinkedList
}
func (next * LinkedList) prepend( value interface{} ) *LinkedList {
return &LinkedList { value, next }
}
func tail( value interface{} ) *LinkedList {
return &LinkedList { value, nil }
}
func traverse( item * LinkedList ) {
if item == nil {
return
}
fmt.Println( item.value )
traverse( item.next )
}
上面这段代码有那些别扭的地方呢?
由于Go缺乏meta-programming能力,所以每个节点的value值必须得是interface {}。也就是说链表可以使用下面的方式构造,却不会触发任何的compiler complaint。当这样的需求充斥整个代码间,Go所拥有的静态类型优势也就消失殆尽了。
stupidList := tail(1991).prepend("CAT").prepend([]byte{1, 16})
我们知道在C-families语言里,当链表结束时,都喜欢储存一个特定的指针(NULL),作为约定俗成的终点,同样在函数错误结束时,通常也会有相似的行为。但空指针是一个非常危险的东西,程序员很可能由于忘记检查其是否为NULL而导致程序崩溃,编译器的类型系统也无法对其作出任何的保证,因为程序员可以简单的把空指针声明为任何类型。
在函数错误验证上,Go试图采用multiple return的方式额外返回一个failure解决这个问题,但与返回空指针没有本质区别,都丢掉了编译期检查。实际上在functional programming里早就有相应的解决办法了——Algebraic Types。
以Haskell为例:
-- 用End作为链表终点
data List t = End | Cons t ( List t )
let my_list = Cons 3 ( Cons 6 ( Cons 9 End ) )
-- 用Nothing作为函数执行错误或者空的结果
search [] = Nothing
search (h:tails) = if h == 1 then Just h else search tails
其次,Go不支持任何内置算子以及关键字扩展的操作。Go为了避免过度复杂化的设计,实际上使得编码工作变得更加复杂了。
以数学矩阵运算为例,对于矩阵的加操作,我希望可以通过“+”算子来进行,以使它更像是内置的数据类型。在Python里,我可以重载__add__()来完成这一目的,只因为Python/c++等等这些语言都将算子视作函数。我甚至可以通过重载iterator的行为,来达成for遍历器的效果。
for item in MyType: ...
最后,说一说Go体系里最亮眼的goroutine和chan。我觉得并发如果想要做成语言层面的syntactic sugar,都没有办法绕过大并发(massive concurrency)、竞争条件(race condition)、错误处理(error handling)这三个问题;
在大并发方面,Go解决得很好,但本质也就是user-space thread,并不是什么先进的技术;
竞争条件本质上是多个逻辑流对同一片内存进行no-sync操作而产生的。最简单的办法就是避免写操作,比如Haskell中的做法,从根本上取消了变量的重复写操作,竞争条件也就无从说起。但在实际的工作中,总是没有办法避免去操作global-state,也没有办法严格的按照函数式编程去避免side-effects。
那么我们可以稍微退一步,采取一种较弱的模型——保证每个逻辑流都使用独立的内存空间,限定一些受到约束的方法进行沟通。在Erlang中,采用了这种严格的进程内存模型,进程间的交流只能通过传递消息来发生。Go启用Chan通道基本也是这个思路,但出于效率的考量(传递消息需要复制操作),没有做任何强制性的保证,依然可以轻松地对共享内存进行访问。程序的正确性只依赖于程序员正确使用并严格遵守slogan。
do not communicate by sharing memory; instead, share memory by communicating.
另外,相对比于Erlang,Go中对于创建的协程缺乏定位能力(no identity),协程之间也并不是完全独立的(no process isolation)。当系统异常发生(比如除零),往往会当掉整个程序,而不能进行状态回退与恢复操作。
当然在并发和协程错误处理上,毕竟是不同的模型,各有取舍,谁优谁劣因看法而异了。
------
知乎回答里面敲代码不能识别TAB真是太难受了。该at谁来改善下?
王垠当初喷windows的时候也是用这个逻辑。虽然他后面道歉了,说windows比linux好的多。
这么多年来,产品研发里的产品设计、项目管理、架构管理都发展了很多。
但是语言并没有进步。
对于项目而言:需要的是工程语言,不是理论语言。 语言发展到今天,也需要用产品经理的逻辑
好坏的发展标准应该是:无到有,从有到好,从好到合适。
设计复杂并不难,难的是满足用户绝大部分需求的情况下,又能设计成极简单。
对很多场景来讲,go是一门合适的语言。每一个设计点都是一种权衡。
语法设计、面象对象设计、并发设计,每一个都是精心思考过的。
其目的就是让你用最小的成本获取最大的收益(最小的开发时间、最小的bug、更高的系统性能和稳定性)。
说它简单是因为它的关键字和语法很少,有其他类c编程语言基础的基本上1天学习时间就能开发项目;
说它又不简单是因为这门语法看似简单的语言实际上要写出架构良好,性能和稳定性合格的程序来不是那么容易的,当然这也可以理解成目前这门语言还不够成熟,在易用性方面做得不够成熟,有一些大家所谓的“坑”,但这个"坑"不是什么语言设计上大的失误导致的。很明显的例子就是,c语言很多人说它简单,但实际上写出好的c程序项目是非常需要功力的,这一点Go很像C。
说它外表丑陋是因为Go是一门非常注重实用性的语言,为软件工程而设计,非出自学院派,甚至很多设计在学院派看来是不可饶恕的(例如not-null,并发编程中的immutable不可变性等等)。它又是一门有态度的语言,例如对左花括号位置的强制要求等等,在很多人看起来这是那些unix大佬们随意而为之的。
说它貌似丑陋的外表另有考究是因为这些看似随意的不负责任的设计实际上绝不是拍拍脑袋任意做出的决定,而是出于实用性的思考在里面。worse is better。下面我就我自己体会到的一点举例如下:
Go语言的时间格式化处理(time包)和其他主流语言有很大的不同,
php Y-m-d H:i:s
java yyyy-MM-dd HH:mm:ss
mysql %Y-%m-%d %H:%I:%S
在Go语言里却使用的是一个特定的时间作为时间格式:
2006-01-02 15:04:05 -0700
一眼看过去,肯定会大骂这个太坑爹了,很丑,怎么会这么设计?
其实这个比上面的方便好记,可读性也更好。
1 2 3 4 5 6 7
月日时分秒年时区
只需记住1234567,比%yyyy%mm这种记法简单多了(对比一下这里的Python strftime reference,即使你多次翻看文档依然不能完全记住相应的规则)。简单粗暴但是实用。
类似的例子还有switch v.(type)简单实现模式匹配的功能而不用复杂化语言类型系统本身。
这种思路彻底贯穿于整个Go语言的设计中,有很多聪明的苦心设计隐藏在其中。
当然,就像任何程序都有bug一样不可避免,Go里面也有一些设计的不好(warts)的地方,相信随着使用的人的增多,语言不断的进化,这些问题会得到解决的。总体来说,Go是一门值得试试看的新语言。
贴个链接,供参考,说明还是有很多人和我一样的看法。:Time in Go | Hacker News
另外两者一个共同特点是,发布的时候要带一堆依赖包或者运行环境,比如说我要写一个监控某个状态的程序放到服务器上,要么选择优雅的方式引入各种包,要么用基本库强行达到需要的效果。如果 go 的话就不存在这个问题。
而且真的很好理解,很容易上手。
习惯了 class 的概念可能不太容易理解 interface,但是一旦进入 interface 的思维就会觉得比 class 更加的优雅。
另外傍 Google 的大树应该没错吧?
另一个,就是说在多线程以及相关的资源控制上更简单.
最后就是说,上手易学之类的.
但是,我的感觉有点相反,目前go语言好像没有表现出上手易学之类的,而且官方相关的文档也不够全面.第三方包和相关的解决方案离java还太远.
看到一些开发者有说有go做web开发的,反正我一直没有看到相关的比较好的demo,而我又不想放弃现有的稳定技术,去用到现在的生产服务中.一直也没有深入的去试试,如果有更强的大神出来现身说法,就再好不过了.
如果你是想用来做商业级的开发,建议再等等看.
1. 有Google这个大厂在背后撑腰,语言设计质量值得期待;
2. 有活跃社区支持,组件/产品的开发和使用值得发掘,服务质量值得期待;
3. 各种相关基础设施完备好用;
4. 语言学习难度低,上手快,人力资源培养速度和质量便于估量;
5. 有望成为Google下一代的统一开发平台,彻底摆脱Java的阴影。
不能忍的缺点是没有泛型,身为一个静态语言,没有泛型,只能用interface,好伤
优点:
1. 保留但大幅度简化指针
2. 多参数返回
3. Array,slice,map等内置基本数据结构
4. Interface
Golang最让人赞叹不易的特性,就是interface的设计。任何数据结构,只要实现了interface所定义的函数,自动就implement了这个interface,没有像Java那样冗长的class申明,提供了灵活太多的设计度和OO抽象度,让你的代码也非常干净。千万不要以为你习惯了Java那种一条一条加implements的方式,感觉还行,等接口的设计越来越复杂的时候,无数Bug正在后面等着你。
同时,正因为如此,Golang的interface可以用来表示任何generic的东西,比如一个空的interface,可以是string可以是int,可以是任何数据类型,因为这些数据类型都不需要实现任何函数,自然就满足空interface的定义了。加上Golang的type assertion,可以提供一般动态语言才有的duck typing特性, 而仍然能在compile中捕捉明显的错误。
5. OO
6. Goroutine
7. 更多现代的特性
如果你是Python和动态语言狂热爱好者,Go不一定能给你带来很大的惊喜,这纯粹取决于你得项目性质,考虑到Python目前在很多地方都用C做核心运算,速度在大部分情况下都不是大问题。scalability是一个问题,但并不是人人都会遇到的。
如果你是C爱好者,强烈建议你学习和使用Go。Go可以调用C/C++程序,又提供了太多的便利,速度上稍有牺牲,但并不大。在绝大部分场景下Go能给你带来媲美C的性能,而对于某些确实性能过于关键的场合,也可以通过cgo让Go和C搭配。
如果你是Java爱好者,除非你是做Android这种不得不用Java的平台,否则也建议你尝试学习Go,这个开发上感觉的差异如同比较开载着1吨石头的拖拉机和开保时捷911那么明显,而Java能给你的,Go能给得更好。
如果你是C++爱好者,!@#$%^&*,恭喜你,至少你的智商应该是没问题的。人生苦短,赶紧脱离C++这个苦海吧。你用来学89个C++高级特性的时间,估计已经用Go写了64个开源项目了。
如果你是像我一样的C和Python的爱好者,对动态语言又没有特殊的热爱……我还需要说什么呢?
让我们荡起双桨,去遨游Golang的海洋吧。
refer:使用Go语言一段时间的感受
七牛云存储
- 产品网址:云存储首页 七牛云存储
- 应用范围:整个产品(包括基础服务、Web端、统计平台、各类小工具等等)
- QOR官网: QOR: E-commerce & CMS SDK written in Go
- github地址: qor/qor · GitHub
- 应用范围: 整个产品
- 产品网址:【美团网团购】吃喝玩乐好帮手,专业品质团购网
- 应用范围:支撑主站后台流量(排序,推荐,搜索等),提供负载均衡,cache,容错,按条件分流,统计运行指标(qps,latency)等功能。
- 产品网址:Weico-最具人气的微博客户端
- 应用范围: 服务端所有代码
- 产品网址:仙侠道官网 - 心动游戏
- 应用范围: 游戏服务端(通讯、逻辑、数据存储)
- 网址:快玩小游戏,单机游戏,网页游戏,快玩游戏,快玩游戏盒
- 应用范围:实时消息系统、用户认证、用户会话、统一统计接口
- 网址:微看|微看电视
- 应用范围:服务接口,后台流程服务,消息系统,图片系统
- 网址:盛大云计算
- 应用范围:CDN的调度系统、分发系统、监控系统、短域名服务,CDN内部开放平台、运营报表系统以及其他一些小工具等
- 网址: 京东云
- 应用范围:后台所有服务全部用go实现
- 网址: http://www.bgitechsolutions.com
- - 应用范围:后台用go实现,调用R实现统计分析,分析结果传递给前端的Highcharts
- 网址:群策 - 统一团队沟通,高效完成工作
- 应用范围:全系统
- 网址:BiddingX_专业的DSP解决方案供应商
- 应用范围:竞价投放、曝光统计、点击跳转
- 产品网址:Bmob移动后端云服务平台
- 应用范围:Restful API(使用Beego)、统计分析平台、常用服务如发邮件、队列异步处理、统计用户空间和接口请求
- 网址:首页 - 街坊四邻
- 应用范围:后台服务
- 网址:www.mi.com
- 应用范围:秒杀系统,日志平台,验证码服务
- 网址:Leanote
- 网址:BearyChat
- 网址:白板
性能上,虽然是静态编译,和 c 差距还很大。简单易用不如在控制台里直接跑的动态语言。
和 python 比 go 的发展不够,第三方库不多,编程语言排名很后。python 模块,文档都很完善,适合作为计算机入门语言。
之前 @Rio 说的多线程。python 可以用多进程加协程的方式利用多核,并不会占用更多的系统资源,而且协程可以利用 epoll /kqueue 和物理栈切换方式实现,性能大家可以实测下,还是相当给力的。代码可以看 gunicorn,wsgi 服务器,写的蛮好。
回到一开始的问题上,go 语言并没有什么好不好,主要是看你能不能快速的生产可靠的代码。
有疑问加站长微信联系(非本文作者)