Go - Wikiwand
For faster navigation, this Iframe is preloading the Wikiwand page for Go.

Go

维基百科,自由的百科全书

Go
编程范型 编译型可平行化结构化指令式
设计者罗伯特·格瑞史莫英语Robert Griesemer
罗勃·派克(Rob Pike)
肯·汤普逊(Ken Thompson)
实现者 Google
发行时间 2009年11月10日,​10年前​(2009-11-10
稳定版本
1.13.3
( 2019年10月17日,​33天前​(2019-10-17[1]
操作系统 LinuxmacOSFreeBSDWindows
许可证 BSD
网站 https://golang.org/
主要实现产品
gc (8g,6g,5g),gccgo
启发语言
COberonLimboNewsqueak[2]

Go(又称Golang[3])是Google开发的一种静态强类型编译型并发型,并具有垃圾回收功能编程语言

罗伯特·格瑞史莫英语Robert Griesemer罗勃·派克(Rob Pike)及肯·汤普逊于2007年9月开始设计Go,[2],稍后Ian Lance Taylor、Russ Cox加入项目。Go是基于Inferno操作系统所开发的。[4]Go于2009年11月正式宣布推出,成为开放原始码项目,支持LinuxmacOSWindows等操作系统。[5] 在2016年,Go被软件评价公司TIOBE 选为“TIOBE 2016 年最佳语言”。[6] ​ 当前,Go每半年发布一个二级版本(即从a.x升级到a.y)。

描述

Go的语法接近C语言,但对于变量的声明英语type declaration有所不同。Go支持垃圾回收功能。Go的并行计算模型是以东尼·霍尔通信顺序进程(CSP)为基础,采取类似模型的其他语言包括OccamLimbo[2],但它也具有pipeline模型的特征,比如通道传输。在1.8版本中开放插件(Plugin)的支持,这意味着现在能从Go中动态加载部分函数。

与C++相比,Go并不包括如枚举异常处理继承泛型断言虚函数等功能,但增加了 切片(Slice) 型、并发、管道、垃圾回收功能接口等特性的语言级支持[2]。Go 2.0版本将支持泛型[7],对于断言的存在,则持负面态度,同时也为自己不提供类型继承来辩护。

不同于Java,Go原生提供了关联数组(也称为哈希表(Hashes)或字典(Dictionaries)),就像字符串类型一样。

撰写风格

Go有定义如下的撰写风格

  1. 每行程序结束后不需要撰写分号(;)。
  2. 大括号({)不能够换行放置。
  3. if判断式和for循环不需要以小括号包覆起来。
  4. 使用 tab 做排版

除了第二点外(换行会产生编译错误),在不符合上述规定时,仍旧可以编译,但使用了内置gofmt工具后,会自动整理代码,使之符合规定的撰写风格。

项目架构

Go的工作区英语Workspace的目录结构如下[8]

src
pkg
bin

三个目录的用途分别为

目录 用途
src 引用的外部
pkg 编译时,生成的对象文件英语Object file
bin 编译后的程序

举例来说,整个项目目录可能会如下:

bin/
    hello                          # 生成的執行檔
    outyet                         # 生成的執行檔
pkg/
    linux_amd64/
        github.com/golang/example/
            stringutil.a           # 編譯時,生成的對象檔案
src/
    github.com/golang/example/
        .git/                      # 外部 Git 庫的詮釋資料
	hello/
	    hello.go               # Git 庫的程式碼
	outyet/
	    main.go                # Git 庫的程式碼
	    main_test.go           # Git 庫的程式碼(測試用的程式)
	stringutil/
	    reverse.go             # Git 庫的程式碼
	    reverse_test.go        # Git 庫的程式碼(測試用的程式)
    golang.org/x/image/
        .git/                      # 外部 Git 庫的詮釋資料
	bmp/
	    reader.go              # Git 庫的程式碼
	    writer.go              # Git 庫的程式碼

特色

Go的主要的功能在于令人简易使用的并行设计,这个方法叫做Goroutine,透过Goroutine能够让程序以异步的方式运行,而不需要担心一个函数导致程序中断,因此Go也非常地适合网络服务。假设有个程序,里面有两个函数:

func main() {
    // 假設 loop 是一個會重複執行十次的迴圈函式。
    // 迴圈執行完畢才會往下執行。
    loop()
	// 執行另一個迴圈。
	loop()
}

这个时候透过Go让其中一个函数同步运行,如此就不需要等待该函数运行完后才能运行下一个函数。

func main() {
    // 透過 `go`,我們可以把這個函式同步執行,
    // 如此一來這個函式就不會阻塞主程式的執行。
    go loop()
	// 執行另一個迴圈。
	loop()
}

Goroutine是类似线程的概念(但Goroutine并不是线程)。线程属于系统层面,通常来说创建一个新的线程会消耗较多的资源且管理不易。而 Goroutine就像轻量级的线程,但我们称其为并发,一个Go程序可以运行超过数万个 Goroutine[9],并且这些性能都是原生级的,随时都能够关闭、结束。一个核心里面可以有多个Goroutine,透过GOMAXPROCS参数你能够限制Gorotuine可以占用几个系统线程来避免失控。

在内置的官方包中也不时能够看见Goroutine的应用,像是net/http中用来监听网络服务的函数实际上是创建一个不断运行循环的Goroutine。

编译器

当前有两个Go编译器分支,分别为官方编译器gc和gccgo。官方编译器在初期使用C写成,后用Go重写从而实现自举英语Bootstrapping (compilers)[10]。Gccgo是一个使用标准GCC作为后端的Go编译器[11]

官方编译器支持跨平台编译(但不支持CGO),允许将原始码编译为可在目标系统、架构上执行的二进制文件。

示例

下面是用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去实现一个像Unix中的Echo命令程序[12]

package main

import (
	"os"
	"flag"
)

var omitNewline = flag.Bool("n", false, "don't print final newline")

const (
	Space   = " "
	Newline = "\n"
)

func main() {
	flag.Parse() // Scans the arg list and sets up flags
	var s string = ""
	for i := 0; i < flag.NArg(); i++ {
		if i > 0 {
			s += Space
		}
		s += flag.Arg(i)
	}
	if !*omitNewline {
		s += Newline
	}
	os.Stdout.WriteString(s)
}

同名争议

Go的名称与2003年发表的编程语言Go!英语Go!_(programming_language)雷同。

参考文献

外部链接


{{bottomLinkPreText}} {{bottomLinkText}}
Go
Listen to this article