Go语言简介
Go语言是Google(谷歌)公司开发的一款静态型、编译型并自带垃圾回收机制和并发的编程语言。
Go语言的风格类似于C语言。其语法在C语言的基础上进行了大幅的简化,去掉了不需要的表达式括号,循环也只有for一种表示方法,就可以实现数值、键值等各种遍历。
Go语言最有特色的特性莫过于goroutine。Go语言在语言层可以通过goroutine对函数实现并发执行。goroutine类似于线程但并非是线程,gouroutine会在Go语言运行时自动调度。因此,Go语言非常适合用于高并发网络服务的编写。
Go语言的特性
-
编译输出可执行文件
Go语言的代码可以直接输出为目标平台的原生可执行文件。Go语言不使用虚拟机,只在运行时(runtime)提供垃圾回收(GC)和goroutine调度。
Go语言使用自己的链接器,不依赖任何操作系统的编译器、链接器。因此编译出来的可执行文件可以直接运行在几乎所有的操作系统和环境中。
从Go1.5版本之后,Go语言实现自举,实现了使用Go语言编写Go语言编译器以及所有工具链的功能。
示例代码,Go语言版的Hello world!
//helloworld.go package main import "fmt" func main(){ fmt.Println("Hello,World!") }
编译可执行文件命令: go build ./helloworld.go
编译完成后,会在当前目录下生成helloworld可执行文件。
Go语言不仅可以输出可执行文件,还可以编译能导出C语言的静态库、动态库。同时,从Go1.7版本开始,Go语言支持将代码编译为插件。使用插件可以动态加载需要的模块,而不是一次性将所有的代码编译成一个可执行文件。
2. 工程结构简单
Go语言的源码无须头文件,编译的文件都来自于后缀名为go的源码文件;Go语言无须解决方案、工程文件和Makefile。只要将工程文件按照GOPATH的规则进行填充,即可使用go build
或者go install进行编译,编译安装的二进制可执行文件统一放在bin目录下。
3. 编译速度快
Go语言可以利用自身的特性实现并发编译,并发编译的最小单元是包(package)。从Go1.9版本开始,最小并发编译单元缩小到函数,整体编译速度提供了20%。
另外,Go语言语法简单,具有严谨的工程结构设计、没有头文件、不允许包的交叉依赖等规则,在很大程度上加快了编译的过程。
4. 高性能
Go语言的性能表现接近于Java语言。
5. 原生支持并发
Go语言的特性就是从语言层原生支持并发,无须第三方库,Go语言可以轻松地在Go语言运行时帮助开发者决定怎样使用CPU资源。
Go语言的并发是基于goroutine,goroutine类似于线程,但并非是线程。可以将goroutine理解为一种虚拟线程。Go语言运行时会参与调度goroutine,并将goroutine合理地分配到每个CPU中,最大限度地使用CPU性能。
多个goroutine中,Go语言使用通道(channel)进行通信,程序可以将需要并发的程序设计为生产者和消费者模式,将数据放入通道。通道的另一端的代码会将这些数据进行并发计算并返回结果,如下图所示。
示例,生产者、消费者并发处理。生产者每秒生成一个字符串,并通过通道传递给消费者,生产者使用两个goroutine并发运行,消费者在main()函数的goroutine中进行处理。
/* 程序描述:生产者每秒生成一个字符串,并通过通道传递给消费者,生产者使用两个goroutine并发运行,消费者在main()函数的goroutine中进行处理。 */ package main import ( "fmt" "math/rand" "time" ) //数据生产者 func producer(header string, channel chan<- string){ //无限循环,不停地生产数据 for{
//使用rand.Int31()生成一个随机数,使用fmt.Sprintf()函数将header和随机数格式化为字符串 channel <- fmt.Sprintf("%s: %v", header, rand.Int31()) //等待1秒 time.Sleep(time.Second) } } //数据消费者 func consumer(channel <-chan string){ //不停地获取数据 for{ //从通道中取出数据,此处会阻塞直到通道中返回数据 message := <-channel //打印数据 fmt.Println(message) } } func main(){ //创建一个字符串类型的通道 channel := make(chan string) //创建producer函数的并发goroutine go producer("cat", channel) go producer("dog", channel) //数据消费函数 consumer(channel) }
6. 强大的标准库
Go语言的标准库覆盖网络、系统、加密、编码、图形等各个方面。比如说,可以直接使用http包进行HTTP协议的收发处理;网络库基于高性能的操作系统通信模型(Linux的epoll、Windows的IOCP);所有的加密、解密都内建支持,不需要从第三方库获取。Go语言的编译器也是标准库的一部分,通过词法器扫描源码,使用语法树获得源码逻辑分支等。Go语言的周边工具也是建立在这些标准库上。在标准库上几乎能完成大部分的需求。
Go语言的标准库以包的方式提供支持,下表是Go语言标准库中常见的包及其功能。
Go语言标准库包名 | 功能 |
bufio | 带缓冲的I/O |
bytes | 实现字节操作 |
container | 封装堆、列表、和环形列表等容器 |
crypto | 加密算法 |
database | 数据库驱动和接口 |
debug | 各种调试文件格式访问及调试功能 |
encoding | 常见算法如JSON、XML、Base64等 |
flag | 命令行解析 |
fmt | 格式化操作 |
go | Go语言的词法、语法树、类型等。可通过这个包进行代码信息提取和修改 |
html | HTML转义及模版系统 |
image | 常见图形格式的访问和生成 |
io | 实现I/O原始访问接口及访问封装 |
math | 数学库 |
net | 网络库,支持Socket、HTTP、Email、RPC和SMTP等 |
os | 操作系统平台不依赖平台依赖封装 |
path | 兼容各操作系统的路径操作实用函数 |
plugin | Go1.7加入的插件系统。支持将代码编译为插件,按需加载 |
reflect | 语言反射支持。可以动态获得代码中的类型信息,获取和修改变量的值 |
regexp | 正则表达式封装 |
runtime | 运行时接口 |
sort | 排序接口 |
strings | 字符串转换、解析及实用函数 |
time | 时间接口 |
text | 文本模版及Token词法器 |
7. 代码风格清晰、简单
Go语言的语法风格类似于C语言,同时在C语言的基础上取其精华,去其糟粕,将C语言中较容易发生错误的写法进行了调整,做出相应的编译提示。
(1)去掉循环冗余括号
//C语言的for循环 for(int i=0; i<10; i++){ //循环代码 } //Go语言的for循环 for i:=0; i<10; i++{ //循环代码 }
在Go语言中,for两边的括号去掉了,int声明变量类型被简化为 ":=" ,在编译时,编译器可以直接通过“:=”右值推导出变量 i 的类型。
(2)去掉表达式冗余括号
同样的简化也可以出现在判断语句中,下面示例是C语言和Go语言的判断语句的比较:
//C语言的判断语句 if(表达式){ //表达式成立 } //Go语言的判断语句 if 表达式 { //表达式成立 }
(3)强制的代码风格
Go语言中,左括号"("必须紧接着语句不换行。其他样式的括号将被视为代码编译错误。示例如下:
//正确的代码风格 for i:=0; i<10; i++{ //循环代码 } //错误的代码风格 for i:=0; i<10; i++ { //循环代码 }
第2种错误的代码风格,在编译的时候会报编译错误。Go语言的这种在语言层面上进行强制的代码风格限制,可能会让开发者刚开始的时候会很有些不习惯。同时,Go语言也提供了一套格式化工具。一些Go语言的开发环境或者编辑器在保存代码时,都会使用格式化工具进行修改代码的格式化,让代码提交时已经是统一格式的代码。
(4)不再纠结于i++ 还是 ++i
在Go语言中,自增操作符不再是一个操作符,而是一个语句。因此,在Go语言中,自增只有一种写法:i++
如果写成前置自增:++i,或者赋值后自增:a = i++,都将导致编译错误。
Reference
Go语言的几大优势和特性 https://blog.csdn.net/u010429831/article/details/100096509