从C++到GO
刚开始接触Go语言,看了两本Go语言的书,从c++开发者的角度来看看go语言的新特性,说下自己感触较深的几点:
并发编程
Go语言层面支持协程,将并发业务逻辑从异步转为同步,大幅提高开发效率;
在c++中,做并发编程目前主流的方案是事件驱动(单线程/多线程/多进程模型等),而事件驱动就需要一个IO多路复用的分发器(select/epoll),这样,就造成了业务逻辑的断开,在代码层面为异步模型,比如:
1).先是一段业务代码
2).调用IO(业务断裂)
3).IO完成后的后续处理逻辑;
而go中的协程的支持让这样的开发工作就轻松多了,按照同步的方式顺序写业务逻辑,遇到IO也没关系,一个线程中可以创建成上百万个协程,这个协程阻塞了就跑下一个,不需要应用代码层面来负责IO后续调度的处理;
比起自己用C/C++去封装底层或调用libevent之类的库,Go的优势是将事件机制封装成了CSP模式,编程变得方便了,但是需要付出goroutine调度的开销;
ps1:Go语言标准库提供的所有系统调用操作(当然也包括所有同步IO 操作),都会出让CPU 给其他goroutine;
ps2:看过网上的经验数据,同步和异步的开发效率(不是运行效率,指的是出活速度)差不多是4:1,嘿嘿,这个数据好激动~~
关于事件驱动与协程在处理并发上的对比,详见不鳥萬Rio的回答:
https://www.zhihu.com/question/19585576/answer/12424447
垃圾回收
毫无疑问这个好用,有了垃圾回收,不需要开发者自行控制内存的释放,这样可避免一堆问题(重复释放、忘记释放内存、访问已释放的内存等);
当然,c++11引入的智能指针(unique_ptr等)如果在程序中应用的普遍,也可以达到类似垃圾回收的目的;
GC带来的问题也是有的,会造成STW,会有程序停止调度的卡顿;
Go1.5的GC利用各种手段大大缩减了STW的时间。Go语言官方保证,在50毫秒的Go程序运行时间中因GC导致的调度停顿至多只有10毫秒。
(ref:http://www.infoq.com/cn/articles/2015-review-go)
函数多返回值
这在python里算不得什么新鲜事,但对c++来说,要实现函数返回多个数据,要么封装一个结构体,要不就只能通过函数传参实现;
多返回值这玩意,在码字的时候能提升心情愉悦感啊,想想,在要返回多个值的场景,不用再找个地方用一个结构体封装一下,直接返回,多直接:
func getName()(firstName, middleName, lastName, nickName string){
return "May", "M", "Chen", "Babe"
}
错误处理
提到多返回值,就接着说说错误处理,估计多返回值应用最多的场景就是第二个参数传回函数的错误状态;比如以下写法就很常见了:
if result, ok := moreMagic(); ok {
/ Do something with result /
}
c/c++对错误的处理一般都是通过错误码来确定一个函数是否正确调用,因此相比c/c++而言,go的错误处理代码行减少了,看上去也美观优雅;
go引入了3个关键字(defer、panic和
recover)用于标准的错误处理流程;defer关键字的引入,保证错误处理的代码在发现错误时一定能够被调用,不会因为业务分支逻辑上的修改而漏调;
当然,看和谁比了,python的实践者认为没有使用try catch的异常处理机制,让错误处理显得很繁琐;
Russ Cox指出Go语言是为大型软件设计的,Go语言的返回错误方式,不可否认,对于调用者不是很方便,但这样做会让程序中可能会出错的地方显的很明显。对于小程序来说,你可能只想打印出错误,退出程序。对于一些很精密的程序,根据异常的不同,来源的不同,程序会做出不同的反应,这很常见,这种情况中,try + catch的方式相对于错误返回模式显得冗长。
ref:
Go语言的错误处理机制引发争议
http://www.infoq.com/cn/news/2012/11/go-error-handle
函数的地位提升
函数作为“类型”出现,成为了一等公民;可以定义函数类型,将一个函数赋值给函数变量,然后在业务链中传递,这个在c++中只有使用std::function才能做到;
还可以使用匿名函数(对应c++11中的lambda表达式),在语言层面支持函数编程,从而可以对程序进行更加灵活的控制和管理。
强制的编码规范
系统做大做久了,代码质量难免下降;开发人员的代码风格不一致,导致程序中充斥着千奇百怪的命名及类的组织方式;
是的,是个公司就会有代码规范,但那只是写在纸面上的东西,是否真照着执行了,还真不好说;什么后期扫描,不改不给上线?
为工程而生,go强制的编码规范,让人耳目一新,从命名、到代码排列组织方式都有明确的规定,不符合就不能编译通过!这个真得叫好;代码工程不是实现个性张扬的地方;
语法后置,为啥这么搞?
以上聊到的都是go的优点,看一个爽一个;但go的语法,如变量、函数的声明和定义,和我们常见的语言语法相比,都是类型后置,这点着实有些不习惯;
为啥要这么搞?
Rob Pike(go语言的创建者之一)针对这个问题给过解释:不是为了与众不同,而是为了更加清晰易懂。特别是当类型比较复杂时,Go的类型语法要比 C 的容易懂。
详见:
https://www.zhihu.com/question/21656696/answer/19027040
最后,贴几点Go语言的哲学:
Go语言集众多编程范式之所长,并以自己独到的方式将它们融合在一起。程序员们可以用他们喜欢的风格去设计程序。
相对于设计规则上的灵活,Go语言有着明确且近乎严格的编码规范。我们可以通过“go fmt”命令来按照官方的规范格式化代码。
Go语言是强调软件工程的编程语言。它自带了非常丰富的标准命令,涵盖了软件生命周期(开发、测试、部署、维护等等)的各个环节。
Go语言是云计算时代的编程语言。它关注高并发程序,并旨在开发效率和运行效率上取得平衡。
Go语言提倡交换数据,而不是共享数据。它的并发原语Goroutine和Channel是其中的两大并发编程利器。同时,Go语言也提供了丰富的同步工具,以供程序员们根据场景选用。然而,后者就不属于语言级别的支持了。
http://www.infoq.com/cn/articles/go-language-introduction
Posted by: 大CC | 26JAN,2016
博客:blog.me115.com [订阅]
Github:大CC
随机推荐
-
[问题2014A05] 复旦高等代数 I(14级)每周一题(第七教学周)
[问题2014A05] (1) 设 \(x_1,x_2\cdots,x_n,x\) 都是未定元, \(s_k=x_1^k+x_2^k+\cdots+x_n^k\,(k\geq 1)\), \(s_0 ...
-
css 样式大全
字体属性:(font) 大小 {font-size: x-large;}(特大) xx-small;(极小) 一般中文用不到,只要用数值就可以,单位:PX.PD 样式 {font-style: obl ...
-
Dice Possibility
Dice Possibility 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 What is possibility of rolling N dice and th ...
-
ls -l 显示年份
默认情况下ls -l命令只显示月和日,不显示年份: $ ls -llrwxrwxrwx 1 root root 7 Feb 27 16:12 bin -> usr/bin 如要要显示年份,就要使 ...
-
001 Lua相关链接
Lua官网:http://www.lua.org/ Lua for windows地址:http://www.lua.org/download.html Lua教程:http://www.runoob ...
-
Flutter数据持久化入门以及与Web开发的对比
对于大部分安卓或者IOS开发人员来说,App的数据持久化可能是很平常的一个话题.但是对于Web开发人员来说,可能紧紧意味着localStorage和sessionStorage. Web开发 loca ...
-
adb shell dumpsys的使用
该命令用于打印出当前系统信息,默认打印出设备中所有service的信息,可以在命令后面加指定的service name. 有两种方法可以查看service list: 1. adb shell dum ...
-
poj2018(高精度二分+dp)
题意:给你n个数,要你在这n个数里面找到一些连续的数,这些数的数量大于等于m,并且他们的平均值在这n个数里面是最大的....... 思路:先把n个数的最大最小值确定,然后二分枚举平均值,对于每一个连续 ...
-
实战DeviceIoControl系列之四:获取硬盘的详细信息
Q 用IOCTL_DISK_GET_DRIVE_GEOMETRY IOCTL_STORAGE_GET_MEDIA_TYPES_EX只能得到很少的磁盘参数,我想获得包括硬盘序列号在内的更加详细的信息,有 ...
-
WPF 附加事件
在WPF中有许多控件有他们自己的特殊的事件.按钮就是一个例子——它添加了 Click 事件,而其他任何类都没有定义该事件. 这回导致两难的境地.假设在 StackPanel 面板中包装了一堆按钮,并且 ...