您好,欢迎访问三七文档
Golang之美—蔡欣圻、邵聪聪2016-09目录Golang的哲学Golang之美GolangvsJava风靡世界?!我们的先行实践Golang的哲学1、go背景介绍:go语言是google2009年发布的第二版开源编程语言,针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全、支持并行进程。2、go是面向接口、组合编程;3、正交性:语言设计的正交性,保证语言的稳定性和简单,go很好的遵循正交规律,如:goroutine接口、组合等;4、少即是多:有且仅有一种方法把事情做好做对,保持简单行的方法是go语言特性紧提供一种方法,减少重复、冗余,把事情做到极致是go的原则;5、并发语言层面支持:并发更好利用多核没有更强的表现力来模拟真实世界;6、开放性:开源,语言的实现对程序员不是个黑盒子,任何想了解语言实现都可以参与。7、强大的作者阵容:C语言之父、Unix系统之父、Utf8和javascriptV8之父等等Golang之美一、可直接编译成机器码,不依赖其他库,部署就是扔一个文件上去就完成了二、编译器和标准库、三方库都是Go语言实现,完全实现了语言上的自举,任何人都可以轻松根据自己的需求修改源代码,再也不用担心去阅读或者修改C或者C++实现的源码了三、静态类型语言,静态类型的语言就是可以在编译的时候检查出来隐藏的绝大多数问题四、语言层面支持并发,这个就是Go最大的特色,天生的支持并发。天生的基因和整容是有区别的,大家一样美丽,但是你喜欢整容的还是天生基因的美丽呢?Go就是基因里面支持的并发,可以充分的利用多核,很容易的使用并发。五、内置runtime、GC,从1.5开始GC已经逐渐趋于完美,下个版本1.8可以控制在海量存储对象的场景下,保证1ms内的gc耗时六、简单易学,Go语言的作者都有C的基因,那么Go自然而然就有了C的基因,那么Go关键字是25个,但是表达能力很强大,几乎支持大多数你在其他语言见过的特性:继承、多态、接口等。七、丰富的标准库,Go目前已经内置了大量的库,特别是网络库非常强大,是目前标准库最强大的语言之一,基本上平时使用的所有功能都可以在标准库中觅得身影。八、完善的第三方生态环境,你所需要的所有功能都可以在第三方库中找到,而且go的三方库开发非常活跃,这个通过github的统计数据就可以得知,具体的三方库部分列表可以通过awesome-go去查看九、跨平台编译可以在任何一个平台编译其它所有系统和平台的发布版本,例如在mac上编译windows、linux、plan9、fuchsia,编译平台包括i386、amd64、arm等等,所以go在物联网和嵌入式领域特别有优势,编译出来的不仅体积小,而且无需安装任何依赖就可以在嵌入式系统中运行十、内嵌C、C++支持,前面说了作者是C的作者,所以Go里面也可以直接包含c代码,利用现有的丰富的C库,不过其实我们并不提倡这么做,因为Go语言已经足够快,也许只有在数据库底层存储这种场景需要调用C、C++函数去完成一些任务了。十一、内置强大的工具Go语言里面内置了很多标准工具链,包括了代码格式化和风格提示、单元测试、Benchmark、系统profile、代码生成、文档生成等等。例如,gofmt工具,自动化格式化代码,能够让团队review变得如此的简单,代码格式一模一样,对于后续项目的维护非常有优势。很多人都发现go的第三方库的源码非常好阅读,就是因为简洁的语法和统一的代码风格。下面附上Go自带的标准profile工具生成的图(在本地对远程的服务器进行profile),只需一行命令即可:1、系统中各个函数的调用关系和CPU时间分布图:gotoolpprof-web、内存使用大小分布:gotoolpprof-web-alloc_space、内存对象分配数分布:gotoolpprof-web-alloc_objects、强大、简单的benchmark代码:packagebenchimport(testing)//测试Xor性能funcBenchmarkXor(b*testing.B){a:=0fori:=0;ib.N;i++{final:=0fori:=0;i1000;i++{final^=i}a=final}_=a}命令gotest-v-run=none-bench=.-benchmem-benchtime=‘3s’结果BenchmarkXor-820000000310ns/op0B/op0allocs/opPASSokgo_test/bench6.537sGolangvsJava1、面向对象比较:一、类型系统:JAVA中有两套完全独立的类型系统,一套是值类型系统,byte、int、boolean、char、double另一套是以object类型为根的对象类型系统,Integer,HashMap等。值类型系统希望用object类型引用,则需要装箱。而go语言中多数类型都是原生的值类型(避免装箱可以节省大量的内存和CPU),甚至包括一些复合类型如数组(array),结构体(struct)等,并且这些类型都可以有方法。我们可以给任何类型增加新方法。同时Go语言可以通过&获得一个对象的引用如varb=&a二、内存排列:Go因为没有类实例对象这种东东,因此Go的任何变量在内存中都是紧密连续排列的,对于内存的访问速度来说,亲和度是很高的,而且CPU缓存也更加容易命中。三、成员的可访问性:Java中使用private,protected,public,package等关键字进行访问控制。对于Go语言如果希望某个符号可被其他包(package)访问,需要将该符号定义为大写字母开头。小写字母开头的符号只能在包内访。四、继承:Java的继承通过extends关键字完成,不支持多继承。Go语言的继承通过匿名组合完成:基类以Struct的方式定义,子类只需要把基类作为成员放在子类的定义中,并且可以通过调整基类成员的位置改变内存布局(因此Go语言相对其它高级语言可以对内存实现很精细的控制,减少内存占用并提高性能)。五、接口:java中的接口作为不同组件中的契约存在,是强制的,类必须声明实现了某接口,需要从该接口继承。哪怕是两个一模一样的接口但只有名字不一样,也只能根据类所声明的实现接口是否包括该接口来决定该类是否实现该接口,叫做“侵入式”的接口。而GO语言中采用的是非侵入式接口,一个类只需要实现接口要求的所有函数,那我们就说该类型隐式实现了该接口,这个在使用第三方库的时候非常易用,大大减少了库之间的耦合度。GO语言可以通过接口进行接口查询(接口指向的对象是否实现了另外的接口),类型查询等六、多态:Java中的多态实现遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。Java中的多态可以通过基于继承和基于接口两种方法实现。而在go语言一般不允许不同类型的赋值,即不支持传统的多态。interface是一个例外,可以用不同类型进行赋值只要一个类型实现了该接口,我们就可以将该类型的变量赋给该接口的变量。2、多线程比较:JAVA:1.JAVA线程与OS线程1:1(其实这个是与虚拟机实现有关,下面说的都是1:1模式),所以调度由系统来决定的(抢占式)2.JAVA的线程可以设置ThreadID3.JAVA的栈是固定大小的4.JAVA提供很多工具来调试(包括运行期)5.相对来说开销要大很多6.newThread(....).start();7.NIO性能很不错,但是使用和实现起来复杂很多很多GOLANG:1.Goroutine是用户态自己实现的线程,调度方式遇到IO/阻塞点方式就会让出cpu时间(其实也看编译器的实现,如果TA在代码里面插入一些yield,也是可以的。反正现在不是抢占式的。)2.不能设置goroutineID,也拿不到(可以调用CAPI或者自己修改源码暴漏出来,实际上修改起来挺简单的,因为Go的源码写的非常简洁优雅)3.goroutine的栈会自动扩容(初始stack很小,2KB,这也是go程序内存占用很小的原因)4.相对java,多线程调试工具链有待完善,不过我们目前也没有发现需要这种调试的地方,实在需要时通过profile工具和简单的日志就可以(目前有一些第三方的工具,不过因为并不需要,我们也没有使用过)5.开销非常小,同时运行几百万个一点问题都没有6.gofunc(..){}()7.golang的最大特点就是这个goroutine非常简单方便,实现功能,都只要按照人类最直接的思维模式写就好(反正可以开大量的goroutine),不像回调的方式那么碎片化(nodejs),也远远不像NIO那么复杂(netty).一句话:可以用最简单的方式写出来非常高性能的并发golang多线程例子://启动海量子线程执行计算任务packagemainimport(logsyncsync/atomictime)vartotalint32=0funcmain(){//控制子线程的任务执行,等同于Map/Reduce处理wg:=&sync.WaitGroup{}//统计运行时间ts:=time.Now()//启动100万个线程,每个线程执行100次加1的任务,这里使用了锁,防止脏数据fori:=0;i1000000;i++{//go标记的函数,自动在一个新的线程中去执行gofunc(){//控制器的执行任务+1wg.Add(1)//子线程结束时,控制器的执行任务完成deferwg.Done()fori:=0;i100;i++{atomic.AddInt32(&total,1)}}()}//这里主线程休眠一小短时间,防止子线程的任务控制wg.Add(1)还没有触发,主线程就执行完毕time.Sleep(1*time.Millisecond)//等待子线程的任务完成wg.Wait()//输出最终运行时间log.Printf(启动100万个线程并执行计算任务完成,总计耗时:%v(毫秒)\n,time.Now().Sub(ts).Nanoseconds()/1000000)//输出最终结果log.Println(最终计算结果为,total)}结果:2016/09/2117:21:45启动100万个线程并执行计算任务完成,总计耗时:2227(毫秒)2016/09/2117:21:45最终计算结果为1000000003.Web比较这个应该是两者区别最大的地方之一Java:使用Tomcat、jetty容器,或者使用netty中间件,也就是需要依赖第三方的东西Golang:只需要标准库就可以实现很高很高的性能,我们目前用的http和http2、https服务、websocket服务、tcp服务、静态文件服务器,在代码中都不会超过3行,非常非常简洁,因为使用的标准库,控制粒度非常细,可以说你就是自己代码的上帝风靡世界?!1、以下项目基本都是各自领域最火的项目之一,并且使用go作为最核心的语言CaaS:Docker,rkt等PaaS:谷歌的k8s,flynn,deis等2、云存储和存储服务:dropbox(2年时间估值300多亿美元),七牛云、乐视云3、数据库:dgraph(谷歌的开源图数据库)、cockroach,codis,,tidb,bolt,influxdb等4、Api网关:Apple的网关、百度的BFE等等5、监控平台:小米、滴滴、携程、360金融,influxdata(目前国外最后的开源系统监控解决方案),promethus6、软负载均衡:谷歌的seesaw(替代lvs)7、中间件:服务
本文标题:Golang之美
链接地址:https://www.777doc.com/doc-6099349 .html