从 Node.js(JavaScript) 到 Golang,我的开发体验
从语言使用时间上看,我使用 JavaScript 从 2014 年开始,使用 Golang 则是 2018 年。
毕业后第一份工作是以 C++ 工程师身份进入公司,入门是使用 Node.js 开发 C++ addons,然后在领导支持下,开始在公司推广 Node.js,后期全面使用它开发创业项目的前后端。2018 年左右在新公司使用 Golang 重写部分旧项目,自此新项目完全使用 Golang 语言。
我此篇文章中的对比不会深入到底层,也不会做过多比较,非得说哪个好,只是直观的开发经验和感受对比。
学习体验
因为有 C++ 的基础,我在初学 Node.js 时,第一感觉是开发效率高。由于 Js 执行单线程,事件驱动风格,写代码时没有了各种多线程锁、进程间通信、内存申请释放等问题,一下子有种如释重负的感觉。
但事件驱动的编程风格我还是花了比较久的时间才有较深的理解。
学习 Golang 时,因为有了 C++ 和 Node.js 的基础,觉得更简单了,没有什么难以理解的概念,只需掌握些语法和 Go 语言特性就能干活。
从体验上来看, 对比 Node.js, 强类型语言我比较喜欢,避免了很多程序员的犯错机会。
最舒服的还是写并发程序方便,对比写 C、C++ 程序,没啥负担;数据处理的性能、web 程序并发处理请求数量又明显优于 Node.js。唯一不太适应的是 Golang 和 JavaScript 语法的差别有些大,下面会详细讲讲。
语言特性
1)
JavaScript 是解释性的脚本语言,Node 使用了 V8(C++编写) 引擎解释执行Js;Go 语言则先编译后执行。
2)
JavaScript 是弱类型的动态语言,Golang 是强类型的静态语言。在这一点上,我个人比较喜欢强类型语言,严格且有秩序,能有效避免程序员犯错。
3)
JavaScript 通过原型链来支持面向对象编程,但同样也支持函数式编程,因为函数也是对象,函数也可以被保存在变量中。
Golang 是不是面向对象官方的说辞是:
Yes and No.
但我个人认为,Golang 与我对面向对象的理解,不是严格的 OOP 语言,但允许有 OOP 的风格。
4)
两者都支持垃圾自动回收,基本上所有流行的高级语言都支持了这一功能,比起 C 和 C++ 完全手动的内存管理方式, 大大减轻了程序员的负担,并且很大程度避免了程序出错的概率。
5)
Golang 函数支持返回多值,这是 Go 的一大特性。
6)
Golang 错误处理不像传统编程语言,使用 try()catch{},而是利用返回多值的特点,一般判断第二个值 error 是否为空,我很不喜欢这一点,写代码时要写很多类似下面的代码:
ret, err := foo()if err != nil { return err}
如果直接忽略可写成这样:
这样写的话,程序又变得不健壮,非常不严谨。
Js 则支持 try…catch。
7)
Golang 内置数据类型丰富,支持接口和反射。Js 类型主要有以下:
Number(数字)
String(字符串)
Boolean(布尔)
Function(函数)
Object(对象)
null(空)
undefined(未定义)
8)
Golang 对并发编程支持较好,这也是最大的亮点,Go语言引入了用户级线程 goroutine 概念,关于并发编程,Go 的理念是:
Don’t communicate by sharing memory; share memory by communicating.
不要通过共享内存来通信,而应该通过通信来共享内存。
我们还可以利用 通道(channel)在多个 goroutine 之间传递数据。Node.js 则主要是单线程异步事件触发的风格。
9)
Golang 跨平台运行的支持比 Node.js 好些,编译后能在任意主流系统平台执行。Node.js 则需要安装 Node 平台,但现在大家都使用了 Docker,也没什么特大的优势。
语法差别
1)
Golang 完全去掉了多余的符号,Js 是可选的,对我来说,刚开始挺不习惯,因为之前接触到的语言每个语句都有分号”;“,作为语句结束的标志。
2)
Golang 类型放在变量后面,允许 x, y int 这种写法,这一点在刚开始入门的时候我同样不习惯。
3)
Golang 语法格式要求严格,比如if语句中,强制把 “{” 与if放在同一行,不能换行。
JS 则相对灵活。Golang 开发团队还指定了统一的代码风格,提供了 gofmt 来格式化代码,JS 则没有官方要求,开发中团队自己制定风格。
4)
Go 利用原生的 import 关键字通过包的路径导入模块,Node.js 中使用 require 引入。
在导出变量或者函数时,Node.js 使用 module.exports 显式导出。
在 Go 中,任何首字母大写的函数或者变量都会被默认导出,外部模块引入该包都可使用。
5)
Go 变量必须在编译前先声明或初始化才能使用,也可使用操作符 := 做类型推导。Js 则在运行时声明类型。
6)
Go string 类型里面每个元素都是一个 byte,显得相对复杂;
JavaScript 中的字符串 String 是一串 Unicode 字符序列,比较容易理解和使用。
包管理
Go 对于包的获取,用go get命令从远程代码库拉(GitHub,Google Code),依赖扁平化。
不支持 go mod 管理依赖前,非常不方便,又缺乏明确的版本管理,团队开发不同的项目容易导入不一样的版本。
v1.11版本后支持 go mod 并且引入 vendor 目录存放依赖之后体验好多了。
Node.js 的包管理采用 npm 或 yarn,相对成熟和方便,依赖集中存放在 node_modules 目录下,但包的链式递归查找,一层又一层的嵌套,让我在开发中有些苦恼。
测试
写后端代码,单元测试是少不了的。Node.js 单元测试一般我们会引入第三方测试框架 Mocha,以及断言库 should.js。测试用例中直接使用 Mocha 测试 API 中提供的特殊关键字:
describe() 表示任意嵌套的测试用例分组
it() 表示单个测试用例。
Go 语言中,测试包 testing 是内置的,且含有自带的测试指令go test。
测试代码必须写在一个命名为 xxx_test.go 的文件中,它将会在每次执行go test的时候运行,用例有以下特点:
测试函数唯一的参数必须是t *testing.T。
函数名称以 Test 开头,紧接着以大写字母开头的单词或短语。
社区
Node.js 有广泛的社区,因为毕竟是依托 JavaScript 的,发展了这么多年,JavaScript 是 Web 应用程序开发中最常用的语言,比较成熟,社区也非常活跃。
Golang 的社区则小得多,但两者都有自己的基础社区,在国内, Node.js 主要活跃在 https://cnodejs.org。Go 主要是 https://golang.org,https://studygolang.com。
以上是我粗浅的体验。
欢迎讨论!
----------------------
公众号:life-is-x
知乎:OneZero
版权声明: 本文为 InfoQ 作者【Garfield】的原创文章。
原文链接:【http://xie.infoq.cn/article/f0613cecb9badf3c52b28a338】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论