楔子
连续吃了两个月的非布,以为自己躲过了尿酸急剧下降的融晶痛,没想到该来的还是回来,膝盖滑膜四个点集体溶解诱发滑膜炎,卧床在家。今天终于能坐起来了,就来谈一谈Golang,国内习惯叫Go语言。
本语言的名字是 Go ;“golang”来自于其 web 站点网址(go.com 在当时已是一个迪士尼 web 站点地址。),并不是该语言的正确名字。
Go语言号称是“21世纪的C语言”还是有一定道理的,首先看看Go语言的三个大神级的核心开发人员 Rob Pike,Robert Griesemer 和 Ken Thompson 设计出了Go语言,其语言定位为系统编程语言。
Rob Pike,一直以肯大爷为自己的导师的非主流程序员,曾在1980年参加奥运会射箭项目获得银牌,又上过电视参加大卫莱特曼的电视节目《Late Night with David Letterman》,参与开发Unix,又和肯大爷一起开发了UTF-8,在数据结构学方面是全世界工程师的导师,同时他是一个所谓的“全栈工程师”,从操作系统到编译器,又从文本编辑器写到UI界面,再同时,他的老婆(Renee French一名知名的插画师)亲自设计了Go语言的吉祥物Gordon。
写到这里不得不思考国内的教育与国外的教育,固定的思维要求你一生择一事,而国外的大神都是多领域发展的,到底…哪个对?有些迷茫。
Robert Griesemer,Google的工程师,和Rob Pike一起开发Sawzall语言,同时同时参与开发Google’s V8 JS引擎和Chubby。
Ken Thompson,肯大爷早在1983年就获得了图灵奖,Unix的开发者之一,同时开发了B语言以及C语言,你知道,一般简历很短的人说明他实在太牛逼了。
Go语言的产生
据Rob Pike在旧金山的演讲稿中所述,在2007年的时候Rob Pike为了Google庞大的C++程序做一些比较琐碎但是核心的工作,由于C++的厚重导致在Google庞大的分布式编译集群上都需要花45分钟。
Rob Pike认为,C++的特性太多了,简化这门语言必是一门更大的成就,于是Rob Pike和Robert Griesemer讨论,进行C++的优化,他们找到肯大爷,并且说服他一起做一些事情,他们要创造一门新的开发语言,不想再使用C++了。
Rob Pike在开车回家的路上一直在思考,于是他给肯大爷和Robert Griesemer写了一封邮件描述了Go的命名和方法:
Robert:以C语言为原型,修补部分明显的缺陷,去掉垃圾功能,添加一些缺失的功能。
Rob:命名为“Go”,好处有很多,这名字非常简短,容易拼写。工具可以叫做:goc、gol、goa。如果有可交互的调试器/解释器也可以简单地叫它“Go”,后缀名用 .go。
Robert:定义空接口语法:interface{}。所有接口都通过这个实现,因此可以用它代替void*。
在演讲稿中Rob Pike也提到,虽然Go语言是以C为原型,以C++为目标设计,但是并没有太多C++程序员转为Go语言开发,实际上大部分Go程序员都是从Python和Ruby转过来的,其中却少有C++程序员,他认为可能Go和C++的设计里面相差太大,C++希望所有解决方案都能很容易得到,这种思考方式和Go的运转方式并不一样。零成本不是目标,至少零CPU成本不是。Go的目标是解放程序员。
Go并没有包罗万象,你不要期待它什么都有,你也无法精确地控制每一个细节。例如:Go没有RAII,但是你可以使用一个垃圾清理器做替代,虽然你甚至无法使用内存释放函数。
你可以从Go中得到很多易于理解但是强大的工具集来组合出问题的解决方案。它跟别的语言比起来也许没有那么快或者精致,但肯定写起来更简单、读起来更容易,也更易于理解,也许还更安全。
从另一个角度看,Go肯定更加简化:
Python和Ruby程序员转向Go是因为他们不需要学更多的关心却可以获得更好的性能,甚至还可以使用并发特性。
C++程序员不愿意转向Go是因为他们竭尽全力只为了对自己的程序的完全掌控,并不希望这样改变。对于他们,软件并不仅是完成工作,而是做好工作。而对于使用脚本语言的人来讲,重点在实现和创造,这就是为什么。
Go语言的优势
首先说Go 语言是充分利用现代硬件性能又兼顾开发效率而设计的一种全新语言, 是一种跨平台(Mac OS、Windows、Linux 等)静态编译型语言。同时兼顾C++的强大性能和脚本语言的开发效率,根据Go语言的使用者调查发现,目前世界上使用Go语言最多的地区居然是中国,可能也跟中国市场越来越大有关系。
Go语言生来就是做大型项目的,当前 Go 语言主要应用于后端服务的开发,未来随着 Go 项目的完善,在系统、游戏、UI界面、AI、物联网等领域,都将被广泛使用。越来越多的人使用Go语言替代脚本语言,同时在游戏服务器方面使用Go语言替代沉重的C++。由于Go语言与生俱来的高并发特性,关于区块链的研究大多都是使用Go语言,就好像研究爬虫大部分在使用Python一样。
对我一个万年Java狗而言,近期在WEB开发上遇到瓶颈,虽然Spring Boot2+Spring Cloud+Docker解决了我快速开发快速部署的难题,但是,由于公司信息化成本缩水严重(每个非互联网公司的信息部都会遇到的问题)、现有设备陈旧、系统不可扩展、信息孤岛严重等等问题,导致我必须寻找一个最大限度压榨硬件设备、同时轻量化的语言进行系统重构。
这时候Go语言跳了出来,为什么一门系统语言不能拿来做WEB应用呢?因为脚本语言及微服务的发展,越来越多的轻量模块+restful API进行前后台分离,那么开发支持rest的API不就是Go的天然优势领域吗?至于前后台的数据交换方面,Go语言的模版引擎也不比主流的freemarker要差。
阿里云的云栖社区上面有一个讨论,比较了Go语言和Java对系统的消耗,可以看下图的结果。
Go的优势很多,我只是对比Java,实际上Go基于C语言并融合了各类语言优秀的特性,同时进行了极大程度的简化。我们来看几个特性Java和Go的对比来说明:
启动速度
这个理论上并不是在比语言,而是web容器。Go语言由于是直接打包成二进制可执行文件,它的启动是系统层面的启动,和业内的容器来比根本不需要数据支撑,用肉眼就能看出来。
多线程与协程
由于现代硬件CPU的性能溢出,并发编程的意义不言而喻。当然,很多语言都支持多线程、多进程编程,但遗憾的是,实现和控制起来并不是那么令人感觉轻松和愉悦。Go语言不同的是,语言级别支持协程(goroutine)并发(协程又称微线程,比线程更轻量、开销更小,性能更高),操作起来非常简单,语言级别提供关键字(go)用于启动协程,并且在同一台机器上可以启动成千上万个协程。
Java开线程
public class MyThread implements Runnable {
String arg;
public MyThread (String a){
arg = a;
}
public void run (){
//...
}
public static void main (String[] args){
new Thread(new MyThread("Thread1")).start();
//Thread2...
}
}
Go开协程
func run (arg string){
//...
}
func main (){
go run("Goroutine1")
//Thread2...
}
消息通信
Go语言全新的消息通通信组件(姑且叫做组件吧)叫做Channel(这个真的读拆哪哦,不读奢奈哦),在GO语言中,使用基于消息传递的通信方式(而不是大多数语言所使用的基于共享内存的通信方式)进行协程间通信,并且将消息管道(channel)作为基本的数据类型,使用类型关键字(chan)进行定义,并发操作时线程安全。这点在语言的实现上,也具有革命性。
同时Channel并不仅仅只是用于简单的消息通信,还可以引申出很多非常实用,而实现起来又非常方便的功能。比如,实现通过chan类型实现redis连接池、TCP连接池、限流等等,而这些在其它语言中实现起来并不轻松,但GO语言可以轻易做到。
func main (){
pool := make(chan redis.Conn, 10)
for i:= 0; i< 10; i++ {
pool<-redis.Detail(...)
}
}
去掉万恶的try…catch
但凡是用Java开发的人,莫不吐槽万恶的try…catch,恶心、臃肿、但又不得不写。Go语言将错误类型(error)作为基本的数据类型,并且在语言级别不再支持try…catch的用法,这应该算是一个非常大胆的革命性创举,也难怪很多人吐槽GO语言不伦不类。但是跳出传统的观念,GO的开发者认为在编程过程中,要保证程序的健壮性和稳定性,对异常的精确化处理是非常重要的,只有在每一个逻辑处理完成后,明确的告知上层调用,是否有异常,并由上层调用明确、及时的对异常进行处理,这样才可以高程度的保证程序的健壮性和稳定性。下面这个例子出现了几个特性:
- 指针
- error作为返回值输出
- 动态参数
func (tx *Tx) Query(query string, ...inferface{}) (*Rows, error){
retrun tx.QueryContext(..., query, arys...)
}
函数拥有多个返回值
在Java里面我们写函数要进行return
的时候,如果涉及到多个值,往往需要封装到Map里面,这一点上Go借鉴了Python等语言,支持多个返回值,同时由于加入匿名函数,让整个调用过程妙不可言。下面这个例子出现了几个特性:
- 多个返回值
- 简化等待变量类型声明
- 返回值直接进行变量声明
- 简化的变量声明和赋值
func GetServerInfo () (svrIp, svrName, svrDNS string) {
return "svrIp", "svrName", "svrDNS"
}
svrIp, svrName, svrDNS := GetServerInfo()
高性能的HTTPServer
作为出现在互联网时代的服务端语言,面向用户服务的能力必不可少。GO在语言级别自带HTTP/TCP/UDP高性能服务器,基于协程并发,为业务开发提供最直接有效的能力支持。要在GO语言中实现一个高性能的HTTP Server,只需要几行代码即可完成,非常简单,启动速度秒杀其他WEB容器,同时维护成本极低,没有任何外部依赖。
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){
io.WriteString(w, "Hello, World.")
})
http.ListenAndServe(":8080", nil)
}
强制编程规范
GO语言的编程规范强制集成在语言中,比如明确规定花括号摆放位置,强制要求一行一句,不允许导入没有使用的包,不允许定义没有使用的变量,提供gofmt工具强制格式化代码等等。
这一点对于一些程序猿来讲非常不满,有人发表GO语言的N条罪状,里面就不乏对编程规范的指责。但是对我而言或是从工程管理的角度,任何一个开发团队都会对特定语言制定特定的编程规范,特别像Google这样的公司,更是如此。GO的设计者们认为,与其将规范写在文档里,还不如强制集成在语言里,这样更直接,更有利用团队协作和工程管理。
岁数大了就不喜欢各式各样的飘逸写法,与其遵守一个公开的文档,不如直接给我报错来得直接,举个例子,在Go语言里面如果你import
某个包,或者声明了某个变量,但是在后续没有使用,Go在编译时会直接报错,挺好的。
Mac OS中安装和使用Go语言
下载安装
在Mac OS中安装Go语言非常简单,直接去官网下载pkg包就可以了,不过呢,由于一些众所周知的原因,这个网站经常的无法访问。但是下载地址倒是没有被墙,这里我放出最新v1.12版的下载地址
这里安装完毕是自动把环境变量配好的,不需要在额外修改配置文件了(除了GOBIN),此时已经可以进行Go的开发了,不过如果需要使用beego之类的第三方框架,在构建的时候还需要额外配置GOBIN的路径,使用go version
查看当前版本,使用go env
查看当前配置信息
环境变量配置
- 打开终端,
cd ~
进入主目录 -
ls -all
查看所有文件,看是否存在.bash_profile
文件 - 如果不存在,则执行
touch .bash_profile
新建 - 如果存在,则执行
vi .bash_profile
打开进行编辑
在文件中添加如下参数
export GOPATH=/Users/xxxxx/Go
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOBIN
- 保存编辑,然后在执行
source ~/.bash_profile
,完成环境变量的配置 -
go env
查看配置成功后的环境变量
PS:我的Mac OS环境配置完如果需要重启后仍然生效,必须重新执行source ~/.bash_profile
,后来发现由于把终端变得好看点安装了zsh,所以系统默认加载的是~/.zshrc
文件,所以配置完环境变量之后,还需要在在~/.zshrc
文件最后,增加一行source ~/.bash_profile
这样就没问题了。
IDE的选择
你会发现很多网上的文章,包括某些教程里面都一直在强调,Go语言是一门系统语言,所以在进行编程的时候要用记事本,要用vim,这样才更加专业。我不知道这些论点是否正确,我相信一定是真的有大神在用vim进行Go语言的编程,但是对于我来讲,选择一门便捷的编辑器是最快能实现项目的唯一渠道。
支持Go语言的编辑器有很多,LiteIDE、VS Code、Sublime、Eclipse、Vim、GoLand等等,但是对于我需要进行WEB开发来讲,多种语言的高亮和提示是很重要的要求,对~没错,来怼我不专业吧。试用了Goland之后,有一些WEB模版不支持高亮,因此又转回了IDEA,其实应该这样说:
如果你单纯用Go语言进行系统级的编程,那么可以选择LiteIDE、Vim;
但是如果你像我一样使用Go语言进行WEB编程的话,建议你选择Eclipse和IDEA;
IDEA支持Go
关于IDEA的安装和PJ这里就不再赘述,让IDEA支持Go语言非常简单,只需安装这两个插件即可
Go-对Go语言的支持以及设置
Go Template-对Go语言的模版引擎的支持
安装完毕后,就可以在Languages&Frameworks里面进行相关配置,也可以直接创建Go项目了。
思考
在开发WEB应用上,我仍然在考虑是直接使用原生Go还是使用第三方Web框架,比如Beego。即便我已经使用Beego简单搭了一个后台管理系统。
其实从路由管理上就能看出,Go在后台API上面的优势。
有疑问加站长微信联系(非本文作者)