Go仅用标准库就能写大多数的软件。用Node.js时,咱们几乎都是不得不引入一个外部的库, 这样作既增长了部署的时间,也增长了来自第三方软件的潜在隐患。只用标准库能让咱们写的代码更快更安全。javascript
另外值得一提的是,node的代码在跨平台运行时,有时会碰到各类意想不到的问题,而go语言的代码实现跨平台运行时仅仅配置一下gopath便可完美兼容。php
Go对包管理必定有本身的理解。对于包的获取,就是用go get命令从远程代码库(GitHub, Bitbucket, Google Code, Launchpad)拉取。而且它支持根据import package分析来递归拉取。这样作的好处是,直接跳过了包管理中央库的的约束,让代码的拉取直接基于版本控制库,你们的协做管理都是基于这个版本依赖库来互动。细体会下,发现这种设计的好处是去掉冗余,直接复用最基本的代码基础设施。Go这么干很大程度上减轻了开发者对包管理的复杂概念的理解负担,设计的很巧妙。java
可是这样也会产生一系列的问题:node
缺少明确显示的版本。团队开发不一样的项目容易导入不同的版本,每次都是get最新的代码。尤为像我司对开源软件管理很是严格,开源申请几乎是没法实施。linux
第三方包没有内容安全审计,获取最新的代码很容易引入代码新的Bug,后续运行时出了Bug须要解决,也没法版本跟踪管理。git
依赖的完整性没法校验,基于域名的package名称,域名变化或子路径变化,都会致使没法正常下载依赖。咱们在使用过程,发现仍是有很多间接依赖包的名称已失效了(不存在,或又fork成新的项目,旧的已不存维护更新)。github
而Go官方对于此类问题的建议是把外部依赖的代码复制到你的源码库中管理。把第三方代码引入本身的代码库仍然是一种折中的办法。golang
因而市面上就诞生了各类Go包管理工具,如glide,dev等。使用第三方包管理最大的好处是,每一个项目都采用各自独立的包,并且能够很好的控制包的版本,这在团队开发中尤为重要。数据库
而node的包管理我认为就相对好一些了,不论是npm仍是yarn的包版本控制,都是棒棒哒。npm
node是使用JavaScript这门动态语言、弱类型语言,好处天然不言而喻,比较灵活,忽略验证数据的类型和真值判断陷阱所带来的额外负担。可是JavaScript是在运行时进行解释的,这可能会致使错误处理和调试的问题。
go属于静态语言,也是强类型语言,虽然没有动态语言灵活,但有助于数据完整,并能够在编译时查找类型错误。Go 被直接编译成机器码,这就是它速度的来源。使用编译语言调试是至关容易的,由于你能够在早期捕获大量错误。
node只适合IO密集型,它没有提供太多的并发基元。惟一能同时运行的是I/O程序和定时器等,并不适合CPU密集型。
node运行机制:node运行机制是事件循环机制,每次从事件队列中取出一个函数之类的,而后去运行它,若是过程当中发生IO事件,好比利用fs模块写一个文件,或者去数据库查询信息等,node就会将这个IO操做加入到一个线程池中去执行,事件循环在主线程继续执行,当线程池中的事件执行完毕,就会将这个结果放入到主线程中。可是若是遇到计算密集型的任务,由于node是单线程,就会阻塞主线程直到该任务执行完毕才会往下执行,因此node不适合作CPU密集型。
go适合IO密集型一样也适合CPU密集型,你能够在程序运行的任何阶段,建立goruntine去实现并发,而且go提供了channel来实现协程间通讯,很赞有木有。
在操做系统提供的内核线程之上,Go搭建了一个特有的两级线程模型。goroutine是实际并发执行的实体,每一个实体之间是经过channel通信来实现数据共享。关于go的并发及调度原理,戳这里goroutine 调度原理
Go 推荐在错误出现的地方捕获它们,而不是像 Node 同样在回调中让错误冒泡。
node的错误处理是错误前置,golang的错误处理是错误后置。
// Node 的错误处理
foo('bar', function(err, data) {
// 处理错误
}
复制代码
//Go 的错误处理
foo, err := bar()
if err != nil {
// 用 defer、 panic、 recover 或 log.fatal 等等处理错误.
}
复制代码
Go 中的错误处理分为错误和异常两种,那么错误和异常的区别是什么呢?
错误和异常从语言机制上面讲,就是error和panic的区别
错误是指可能出现的地方出了问题,好比打开一个文件失败,这种是在人们的意料之中;
而异常指的是不该该出现问题的地方出现了问题,好比引用了空指针、下标越界、除数为0等,这种状况在人们的意料以外。
Golang中引入两个内置函数panic和recover来触发和终止异常处理流程,同时引入关键字defer来延迟执行defer后面的函数。
使用 Go 的错误处理时,应注意如下几点
失败的缘由只有一个时,不使用error
没有失败时,不返回error
error应放在返回值类型列表的最后
错误值统必定义,而不是跟着感受走
错误逐层往上抛时,层层都加日志,便于定位错误
当尝试几回能够避免失败时,不要当即返回错误
当上层函数不关心错误时,建议不返回error
Node中的错误处理主要分为如下三种状况
异步的函数里,使用throw。使用者使用try...catch便可捕获错误。
异步函数里,更经常使用的方式是使用callback(err, result)的方式。
在更复杂的场景里,能够返回一个EventEmitter对象,代替使用callback。使用者能够监听emitter对象的 error事件。 例如读取一个数据流,咱们可能会同时使用 req.on('data')、req.on('error')、req.on('timeout') 。
因此,使用throw仍是callbacks、EventEmitter,取决于:
该错误是操做错误仍是编码错误?
该函数是同步仍是异步?
在node中进行单元测试须要借助第三方测试框架入mocha以及第三方断言库入should.js,相关文章 Node.js 单元测试:我要写测试
使用Go的时候,咱们喜欢测试框架的规范化。在Go里,全部的测试包都是内置的。若是你须要写一个新的测试套件,你必须作就是把(文件名)_test.go文件加到你要测试的软件的同一个包里,它将会在你每次执行go test的时候运行。
提到单元测试,就不得不提的是测试的覆盖率问题,在go中的测试覆盖率有一点须要注意的地方,在go中计算单元测试覆盖率是不包括没有定义_test.go的模块的,只会统计已经定义了_test.go模块的单元测试覆盖率。
go的部署真的是很是简单,将go build后生成的二进制文件直接丢到服务器上去,而后运行这个程序,不须要任何语言环境,像java程序须要在服务器安装java,php须要安装Apache,PHP等运行环境,go通通不须要,只须要一个linux系统就好,扔上去就能够了。
而node的部署的部署则须要在服务器上安装npm,或者借助pm2,将项目代码拉倒服务器,并跑起来。
Node 和 Go 岁数相仿,社区也相对都比较完整了
做者的 Golang 系列博文: