简介
GO 语言是谷歌在2009年发布的第二款开源编程语言。它专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全、支持并行执行。
Go 的目标是希望提升现有编程语言对程序库的依赖性(dependency)的管理,这些软件元素会被应用程序反复调用。由于支持并行编程模式,因此这一语言也被设计用来解决需要多处理器完成的任务。
特点
- 简洁 快速 安全
- 并行 有趣 开源,
- 内存管理,数组安全,编译迅速
Go 适合用来做什么
- 服务器编程,以前你如果使用 C 或者 C++ 做的那些事情,用 Go 来做很合适,例如处理日志、数据打包、虚拟机处理、文件系统等。
- 分布式系统,数据库代理器等。
- 网络编程,这一块目前应用最广,包括 Web 应用、API 应用。
- 云平台,目前国外很多云平台在采用 Go 开发。
如何编写 Go 代码
编写 Go 代码前,首先有一个概览:
- Go 程序员通常将他们所有的 Go 代码保存在一个工作区中。
- 工作区包含许多版本控制存储库 (例如,由 Git 管理)。
- 每个存储库都包含一个或多个包。
- 每个软件包由一个目录中的一个或多个 Go 源文件组成。
- 包的目录的路径决定了它的导入路径。
但注意,这与其他编程环境不同,在这些编程环境中,每个项目都有一个单独的工作区,工作区与版本控制存储库紧密相关。
关于 Go 的工作区:
工作区是一个目录层次结构,其根目录包含三个目录:
- src 包含 Go 源文件,
- pkg 包含包对象
- bin 包含可执行命令。
该 go 工具构建源包并将生成的二进制文件安装到 pkg 和 bin 目录。
该 src 子目录通常包含多个版本控制存储库(例如 Git 或 Mercurial),用于跟踪一个或多个源包的开发。
导入路径:
一个导入路径是唯一标识一个包的字符串。程序包的导入路径对应于其在工作区内或远程存储库中的位置。来自标准库的软件包被赋予诸如"fmt"和的短导入路径 "net/http"。对于你自己的软件包,你必须选择一个基本路径,这个基本路径不可能与未来添加到标准库或其他外部库中相冲突。
第一个 Go 程序:
要编译并运行一个简单的程序,首先选择一个包路径(我们将使用 github.com/user/hello)并在工作区内创建一个相应的包目录:
$ mkdir $ GOPATH / src / github.com / user / hello
接下来,创建一个名为hello.go该目录内的文件,其中包含以下Go代码。
package main import "fmt" func main() { fmt.Printf("Hello, world.\n") }
现在,您可以使用该go工具构建和安装该程序:
$ go install github.com/user/hello
请注意,您可以从系统上的任何位置运行此命令。该 go工具通过查找github.com/user/hello指定的工作区内的程序包 来查找源代码 GOPATH。
Go语音程序例子:
用Go写成的“hello world”例子:
package main import "fmt" func main() { fmt.Println("Hello, World") }
通过 Go 语言仅需几行程序码就完成 HTTP 网页服务器的实现:
package main import ( "io" "net/http" ) func hello(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "Hello world!") } func main() { http.HandleFunc("/", hello) http.ListenAndServe(":8000", nil) }
Go 语言的垃圾回收
Go 的垃圾回收在1.5版本之前是采用了标记-清理的方法,即先标记出需要清理的内存,然后清理掉。实际上,标记清除法是一种常见垃圾回收算法。下面就介绍一下常见的垃圾回收算法。
常见的垃圾回收(GC)算法
引用计数法
在每个对象内加入一个整数值,这个对象被引用时加一,从被引用的状态中解除时减一,然后清理掉引用计数为0的对象。
这种方法的缺陷在于无法处理循环引用,当对象A与B互相持有对方的引用时,无法回收它们。
标记清除法
顾名思义,这个方法分为标记和清除两步。
标记:从程序的根节点开始,递归地遍历所有的对象以确定所有还在使用的对象,然后标记他们
清除:没被标记的就全部回收就好了
当然了这个算法也会有应该缺陷,在发动时必须暂停整个程序,不然发动时一些对象的状态如果被其他的代码改变,就可能把这些对象中不该回收的回收掉。而且当对象很多时,会消耗很多时间,让整个程序暂停的时间太长对用户体验会造成极其不好的影响。GO 语言1.5之前使用的是这个算法。
三色标记法
这种方法是对标记清理法的一种改进,最大的好处就是不再需要暂停程序了。
- 首先建立三个集合:白,灰,黑,之后把所有的对象放入白集合中。
- 从根节点遍历所有对象,不需要递归,遍历到的对象放入灰集合
- 遍历灰色集合,被灰集合引用的对象从白集合中移到灰集合中,直到灰集合中没有任何对象
- 通过 write-barrier 检测这个过程中对象的变化,有变化时重复上面几步,当对象没有变化时,把灰集合中的对象移入黑集合
- 回收白集合中的对象
这个算法的缺陷就在于,如果程序中垃圾产生的速度大于清理的速度,就会让垃圾无法被清理,这个算法应用于 GO 1.5和 GO 1.6
分代收集法
这个方法也是对标记清理法的一种改进,因为绝大多数对象的生命周期都很短,所以按照它们的生命周期来分代,一般来说是分为三代的:第0代,第1代,第2代
原理如下:
- 新对象视为第0代
- 当内存用量超过一定程度时(通常很低),对第0代进行标记清理
- 没被清理掉的第0代对象归入第1代
- 当内存用量超过一定程度时(通常较高),对第1代进行标记清理
- 以此类推
因为新对象的数量比较少,所以收集时会很快,当内存消耗过大时才触发1代和2代收集,目前在使用这种算法的语言(平台)有 jvm , .NET