简介

GO 语言是谷歌在2009年发布的第二款开源编程语言。它专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全、支持并行执行。

Go 的目标是希望提升现有编程语言对程序库的依赖性(dependency)的管理,这些软件元素会被应用程序反复调用。由于支持并行编程模式,因此这一语言也被设计用来解决需要多处理器完成的任务。

特点

  1. 简洁 快速 安全
  2. 并行 有趣 开源,
  3. 内存管理,数组安全,编译迅速

Go 适合用来做什么

  1. 服务器编程,以前你如果使用 C 或者 C++ 做的那些事情,用 Go 来做很合适,例如处理日志、数据打包、虚拟机处理、文件系统等。
  2. 分布式系统,数据库代理器等。
  3. 网络编程,这一块目前应用最广,包括 Web 应用、API 应用。
  4. 云平台,目前国外很多云平台在采用 Go 开发。

如何编写 Go 代码

编写 Go 代码前,首先有一个概览:

  1. Go 程序员通常将他们所有的 Go 代码保存在一个工作区中。
  2. 工作区包含许多版本控制存储库 (例如,由 Git 管理)。
  3. 每个存储库都包含一个或多个包。
  4. 每个软件包由一个目录中的一个或多个 Go 源文件组成。
  5. 包的目录的路径决定了它的导入路径。

但注意,这与其他编程环境不同,在这些编程环境中,每个项目都有一个单独的工作区,工作区与版本控制存储库紧密相关。

关于 Go 的工作区:

工作区是一个目录层次结构,其根目录包含三个目录:

  1. src 包含 Go 源文件,
  2. pkg 包含包对象
  3. 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之前使用的是这个算法。

 

三色标记法

这种方法是对标记清理法的一种改进,最大的好处就是不再需要暂停程序了。

  1. 首先建立三个集合:白,灰,黑,之后把所有的对象放入白集合中。
  2. 从根节点遍历所有对象,不需要递归,遍历到的对象放入灰集合
  3. 遍历灰色集合,被灰集合引用的对象从白集合中移到灰集合中,直到灰集合中没有任何对象
  4. 通过 write-barrier 检测这个过程中对象的变化,有变化时重复上面几步,当对象没有变化时,把灰集合中的对象移入黑集合
  5. 回收白集合中的对象

这个算法的缺陷就在于,如果程序中垃圾产生的速度大于清理的速度,就会让垃圾无法被清理,这个算法应用于 GO 1.5和 GO 1.6

 

分代收集法

这个方法也是对标记清理法的一种改进,因为绝大多数对象的生命周期都很短,所以按照它们的生命周期来分代,一般来说是分为三代的:第0代,第1代,第2代

原理如下:

  1. 新对象视为第0代
  2. 当内存用量超过一定程度时(通常很低),对第0代进行标记清理
  3. 没被清理掉的第0代对象归入第1代
  4. 当内存用量超过一定程度时(通常较高),对第1代进行标记清理
  5. 以此类推

因为新对象的数量比较少,所以收集时会很快,当内存消耗过大时才触发1代和2代收集,目前在使用这种算法的语言(平台)有 jvm , .NET