在 Linux 上安装 Go

如果你能够自己下载并编译 Go 的源代码的话,对你来说是非常有教育意义的,你可以根据这个页面找到安装指南和下载地址:Download the Go distribution。
我们接下来也会带你一步步地完成安装过程。

1. 设置 Go 环境变量

$HOME/.bashrc$HOME/.profile
    export GOROOT=$HOME/go

为了确保相关文件在文件系统的任何地方都能被调用,你还需要添加以下内容:

    export PATH=$PATH:$GOROOT/bin

在开发 Go 项目时,你还需要一个环境变量来保存你的工作目录。

    export GOPATH=$HOME/Applications/Go
$GOPATHgo get
    Set $GOROOT_BOOTSTRAP to a working Go tree >= Go 1.4.。

所以在安装 Go 1.5 版本及之后的版本时需要设置

    cp go/ $home/go-bootstrap/
    export GOROOT_BOOTSTRAP=$HOME/.golang/go-bootstrap
source .bashrcgo envenv

2. 安装 C 工具

Go 的工具链是用 C 语言编写的,因此在安装 Go 之前你需要先安装相关的 C 工具。如果你使用的是 Ubuntu 的话,你可以在终端输入以下指令

      sudo apt-get install bison ed gawk gcc libc6-dev make

你可以在其它发行版上使用 RPM 之类的工具。

3. 获取 Go 源代码

go$GOROOT
    wget https://storage.googleapis.com/golang/go<VERSION>.src.tar.gz
    tar -zxvf go<VERSION>.src.tar.gz
    sudo mv go $GOROOT

4. 构建 Go

在终端使用以下指令来进行编译工作。

    cd $GOROOT/src
    ./all.bash
net/httpgoogle.com
      ‘make[2]: Leaving directory `/localusr/go/src/pkg/net’
$DISABLE_NET_TESTSnet/http
    export DISABLE_NET_TESTS=1
./make.bash

5. 测试安装

hello_world1.go
    package main

    func main() {
          println("Hello", "world")
    }
go run hello_world1.goHello, world

6. 验证安装版本

go version
    package main
    import (
          "fmt"
          "runtime"
    )

    func main() {
          fmt.Printf("%s", runtime.Version())
    }
go1.4.2

7. 更新版本

你可以在 发布历史 页面查看到最新的稳定版。
当前最新的稳定版 Go 1 系列于 2012 年 3 月 28 日发布。
Go 的源代码有以下三个分支:

  • Go release:最新稳定版,实际开发最佳选择
  • Go weekly:包含最近更新的版本,一般每周更新一次
  • Go tip:永远保持最新的版本,相当于内测版
    当你在使用不同的版本时,注意官方博客发布的信息,因为你所查阅的文档可能和你正在使用的版本不相符。

在 Windows 上安装 Go

$GOPATHc:gogo runfatal error: can’t find import: fmt

在 Windows 下运行在虚拟机里的 Linux 系统上安装 Go
如果你想要在 Windows 下的虚拟机里的 Linux 系统上安装 Go,你可以选择使用虚拟机软件 VMware,下载 VMware player,搜索并下载一个你喜欢的 Linux 发行版镜像,然后安装到虚拟机里,安装 Go 的流程参考第 2.3 节中的内容。

安装目录清单&Go运行时(runtime)&Go解释器

安装目录清单

$GOROOT
/bin/doc/lib/misc/os_arch.a/src/src/cmd

Go 运行时(runtime)

尽管 Go 编译器产生的是本地可执行代码,这些代码仍旧运行在 Go 的 runtime(这部分的代码可以在 runtime 包中找到)当中。这个 runtime 类似 Java 和 .NET 语言所用到的虚拟机,它负责管理包括内存分配、垃圾回收(第 10.8 节)、栈处理、goroutine、channel、切片(slice)、map 和反射(reflection)等等。

$GOROOT/src/runtime

垃圾回收器 Go 拥有简单却高效的标记-清除回收器。它的主要思想来源于 IBM 的可复用垃圾回收器,旨在打造一个高效、低延迟的并发回收器。目前 gccgo 还没有回收器,同时适用 gc 和 gccgo 的新回收器正在研发中。使用一门具有垃圾回收功能的编程语言不代表你可以避免内存分配所带来的问题,分配和回收内容都是消耗 CPU 资源的一种行为。

Go 的可执行文件都比相对应的源代码文件要大很多,这恰恰说明了 Go 的 runtime 嵌入到了每一个可执行文件当中。当然,在部署到数量巨大的集群时,较大的文件体积也是比较头疼的问题。但总的来说,Go 的部署工作还是要比 Java 和 Python 轻松得多。因为 Go 不需要依赖任何其它文件,它只需要一个单独的静态文件,这样你也不会像使用其它语言一样在各种不同版本的依赖文件之间混淆。

Go 解释器

因为 Go 具有像动态语言那样快速编译的能力,自然而然地就有人会问 Go 语言能否在 REPL(read-eval-print loop)编程环境下实现。Sebastien Binet 已经使用这种环境实现了一个 Go 解释器,你可以在这个页面找到:https://github.com/sbinet/igo。

关于go get 问题

在国内采用go get有时会下载不到一些网站如golang.org的依赖包。例如:

    $ go get collidermain
    package golang.org/x/net/websocket: unrecognized import path "golang.org/x/net/websocket" (https fetch: Get https://golang.org/x/net/websocket?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)

这是因为网络的一些原因,有条件的可以使用VPN,以下方法也可以解决:

1: Gopm(Go Package Manager)

Go Package Manager(gopm)是Go的包管理器和构建工具。
git地址:https://github.com/gpmgo/gopm
官方地址:https://gopm.io/gopm
文档路径:https://github.com/gpmgo/docs/tree/master/zh-CN
通过这个命令可以来安装gopm插件,默认的会存放到GOBIN,如果没有配置%GOBIN%环境变量,那么会默认安装到%GOPATH%下的bin目录,为了我们操作方便,我们把GOBIN加到%PATH%下。

      go get -u github.com/gpmgo/gopm

通过gopm get xxx,可以将指定的包下载到gopm的本地仓库~/.gopm/repos(建议使用) 通过'gopm get -g xxx',可以将指定的包下载到GOPATH下。(建议使用) 通过'gopm get -l xxx',可以将指定的包下载到当前所在目录(不常用)

用gopm get -g代替go get
不采用-g参数,会把依赖包下载.vendor目录下面;
采用-g 参数,可以把依赖包下载到GOPATH目录中;

2: install form github

golang 在 github 上建立了一个镜像库,如 https://github.com/golang/net 即是 https://golang.org/x/net 的镜像库
获取 golang.org/x/net 包,其实只需要以下步骤:

      $ mkdir -p $GOPATH/src/golang.org/x  //路径下创建此文件
      $ cd $GOPATH/src/golang.org/x      //切换到此目录
      $ git clone https://github.com/golang/tools.git  //通过git安装 tools
      $ git clone https://github.com/golang/lint.git   //安装 lint 
      $ go get golang.org/x/lint/golint       //然后执行  

其它 golang.org/x 下的包获取皆可使用该方法。
例如,很多go的软件在编译时都要使用tools里面的内容,使用下面方法获取:
进入上面的x目录下,输入:

      git clone https://github.com/golang/tools.git

注意,一定要保持与go get获取的目录结构是一致的,否则库就找不到了。

3: GOPROXY

主要有两个地址:

https://goproxy.io
https://goproxy.cn/

命令行设置 例如

在Mac/linux下执行:
export GO111MODULE=on

Windows平台执行:
SET GO111MODULE=on

我们这里以https://goproxy.cn为例:
在Mac/linux下可以执行以下命令来设置:
export GOPROXY=https://goproxy.cn

Windows平台在cmd执行以下命令来设置:
SET GOPROXY="https://goproxy.cn"
或者在PowerShell中执行:
C:> $env:GOPROXY = "https://goproxy.cn"

4. 删除用go get 安装的package

  1. 手动删除
      It's safe to just delete the source directory and compiled package file. Find the source directory under $GOPATH/src and the package file under $GOPATH/pkg/<architecture>, for example: $GOPATH/pkg/windows_amd64.

直接删除源文件目录及编译后的package目录即可。在源码目录$GOPATH/src下找到你要删除的package名,直接删除;然后在$GOPATH/pkg/下删除编译后的package目标文件目录。

  1. 用go clean命令自动删除编译后的package目录,再手动删除源文件目录
      go get -u github.com/motemen/gore
      # -n 表示只打印命令,不执行
      go clean -i -n github.com/motemen/gore...

      # 执行删除编译后的package目录
      go clean -i github.com/motemen/gore...

      # 如果还有未删除的目录,那只有手动删除了
      $ rmdir $GOPATH/pkg/darwin_amd64/github.com/motemen/gore
      $ rm -rf $GOPATH/src/github.com/motemen/gore
注意:
请一定要包含三个点号 ... ,这样就不会递归删除子package,如本例中的 gore/gocode。-i 参数表示删除由 go install 所创建的archive或二进制文档。

开发环境与工具

https://github.com/avelino/awesome-go
因为 Go 语言还是一门相对年轻的编程语言,所以不管是在集成开发环境(IDE)还是相关的插件方面,发展都不是很成熟。不过目前还是有一些 IDE 能够较好地支持 Go 的开发,有些开发工具甚至是跨平台的,你可以在 Linux、Mac OS X 或者 Windows 下工作。
你可以通过查阅 编辑器和 IDE 扩展 页面来获取 Go 开发工具的最新信息。

调试器

应用程序的开发过程中调试是必不可少的一个环节,因此有一个好的调试器是非常重要的,可惜的是,Go 在这方面的发展还不是很完善。目前可用的调试器是 gdb,最新版均以内置在集成开发环境 LiteIDE 和 GoClipse 中,但是该调试器的调试方式并不灵活且操作难度较大。
如果你不想使用调试器,你可以按照下面的一些有用的方法来达到基本调试的目的:

printprintlnfmt.Printfmt.Printlnfmt.Printffmt.Printf
%+v%#v%T
  1. 使用 panic 语句(第 13.2 节)来获取栈跟踪信息(直到 panic 时所有被调用函数的列表)。
  2. 使用关键字 defer 来跟踪代码执行过程。

构建并运行 Go 程序

gofmta declared and not usedProgram exited with code 0
go buildgo install

格式化代码

go fmtgofmtgofmt
gofmt

Go 对于代码的缩进层级方面使用 tab 还是空格并没有强制规定,一个 tab 可以代表 4 个或 8 个空格。在实际开发中,1 个 tab 应该代表 4 个空格,而在本身的例子当中,每个 tab 代表 8 个空格。至于开发工具方面,一般都是直接使用 tab 而不替换成空格。

gofmt –w program.go-wgofmt -w *.gogofmt map1
gofmt-r<原始内容> -> <替换内容>

实例:

	gofmt -r '(a) -> a' –w *.go

上面的代码会将源文件中没有意义的括号去掉。

	gofmt -r 'a[n:len(a)] -> a[n:]' –w *.go
len(a)
	gofmt –r 'A.Func1(a,b) -> A.Func2(b,a)' –w *.go

上面的代码会将源文件中符合条件的函数的参数调换位置。

gofmt

生成代码文档

go doc

它也可以作为一个提供在线文档浏览的 web 服务器,http://golang.org 就是通过这种形式实现的。

一般用法

go doc packagego doc fmtgodocfmtgo doc package/subpackagego doc container/listgo doc package functiongo doc fmt Printffmt.Printf()
../go/srcgodoc -http=:6060
godoc
godocgodoc

其它工具

Go 自带的工具集主要使用脚本和 Go 语言自身编写的,目前版本的 Go 实现了以下工具:

go installgo clean
  • _obj/ 旧的object目录,由Makefiles遗留
  • _test/ 旧的test目录,由Makefiles遗留
  • _testmain.go 旧的gotest文件,由Makefiles遗留
  • test.out 旧的test记录,由Makefiles遗留
  • build.out 旧的test记录,由Makefiles遗留
  • *.[568ao] object文件,由Makefiles遗留
  • DIR(.exe) 由 go build 产生
  • DIR.test(.exe) 由 go test -c 产生
  • MAINFILE(.exe) 由 go build MAINFILE.go产生
go getgo fixgo fixgo pprofgo testgo versiongo envgo listgo run

与其它语言进行交互

与 C 进行交互

import "C"import "unsafe"import "C"
	// #include <stdio.h>
	// #include <stdlib.h>
	import "C"
C.uintC.longC.random()

当你想要使用某个类型作为 C 中函数的参数时,必须将其转换为 C 中的类型,反之亦然,例如:

      var i int
      C.uint(i) 		// 从 Go 中的 int 转换为 C 中的无符号 int
      int(C.random()) // 从 C 中 random() 函数返回的 long 转换为 Go 中的 int
Random()Seed()C.random()C.srandom()

示例 3.2 c1.go

      package rand
      // #include <stdlib.h>
      import "C"
      func Random() int {
            return int(C.random())
      }

      func Seed(i int) {
          C.srandom(C.uint(i))
      }
C.CString(s)C.GoString(cs)C.free
      defer C.free(unsafe.Pointer(Cvariable))

这一行最好紧跟在使用 C 代码创建某个变量之后,这样就不会忘记释放内存了。下面的代码展示了如何使用 cgo 创建变量、使用并释放其内存:
示例 3.3 c2.go

package print

// #include <stdio.h>
// #include <stdlib.h>
import "C"
import "unsafe"

func Print(s string) {
	cs := C.CString(s)
	defer C.free(unsafe.Pointer(cs))
	C.fputs(cs, (*C.FILE)(C.stdout))
}

构建 cgo 包

你可以在使用将会在第 9.5 节讲到的 Makefile 文件(因为我们使用了一个独立的包),除了使用变量 GOFILES 之外,还需要使用变量 CGOFILES 来列出需要使用 cgo 编译的文件列表。例如,示例 3.2 中的代码就可以使用包含以下内容的 Makefile 文件来编译,你可以使用 gomake 或 make:

include $(GOROOT)/src/Make.inc
TARG=rand
CGOFILES=
c1.go
include $(GOROOT)/src/Make.pkg

与 C++ 进行交互

SWIG(简化封装器和接口生成器)支持在 Linux 系统下使用 Go 代码调用 C 或者 C++ 代码。这里有一些使用 SWIG 的注意事项:

  • 编写需要封装的库的 SWIG 接口。
  • SWIG 会产生 C 的存根函数。
  • 这些库可以使用 cgo 来调用。
  • 相关的 Go 文件也可以被自动生成。

这类接口支持方法重载、多重继承以及使用 Go 代码实现 C++ 的抽象类。

目前使用 SWIG 存在的一个问题是它无法支持所有的 C++ 库,比如说它就无法解析 TObject.h。

VSCode 使用技巧

设置字体

文件->首选项->设置

快捷键的使用

自定义快捷配置:文件->首选项->键盘快捷方式
VSCodA的地捷键不要和输入法冲突,否则不会生效,一些快捷键需要安装Go插件后才能生效

常用的快捷键

按 Press 功能 Function
Ctrl + Shift + P,F1 显示命令面板 Show Command Palette
Ctrl + P 快速打开 Quick Open
Ctrl + Shift + N 新窗口/实例 New window/instance
Ctrl + Shift + W 关闭窗口/实例 Close window/instance
  • 基础编辑 Basic editing
按 Press 功能 Function
Ctrl+X 剪切行(空选定) Cut line (empty selection)
Ctrl+C 复制行(空选定)Copy line (empty selection)
Alt+ ↑ / ↓ 向上/向下移动行 Move line up/down
Shift+Alt + ↓ / ↑ 向上/向下复制行 Copy line up/down
Ctrl+Shift+K 删除行 Delete line
Ctrl+Enter 在下面插入行 Insert line below
Ctrl+Shift+Enter 在上面插入行 Insert line above
Ctrl+Shift+ 跳到匹配的括号 Jump to matching bracket
Ctrl+] / [ 缩进/缩进行 Indent/outdent line
Home 转到行首 Go to beginning of line
End 转到行尾 Go to end of line
Ctrl+Home 转到文件开头 Go to beginning of file
Ctrl+End 转到文件末尾 Go to end of file
Ctrl+↑ / ↓ 向上/向下滚动行 Scroll line up/down
Alt+PgUp / PgDown 向上/向下滚动页面 Scroll page up/down
Ctrl+Shift+[ 折叠(折叠)区域 Fold (collapse) region
Ctrl+Shift+] 展开(未折叠)区域 Unfold (uncollapse) region
Ctrl+K Ctrl+[ 折叠(未折叠)所有子区域 Fold (collapse) all subregions
Ctrl+K Ctrl+] 展开(未折叠)所有子区域 Unfold (uncollapse) all subregions
Ctrl+K Ctrl+0 折叠(折叠)所有区域 Fold (collapse) all regions
Ctrl+K Ctrl+J 展开(未折叠)所有区域 Unfold (uncollapse) all regions
Ctrl+K Ctrl+C 添加行注释 Add line comment
Ctrl+K Ctrl+U 删除行注释 Remove line comment
Ctrl+/ 切换行注释 Toggle line comment
Shift+Alt+A 切换块注释 Toggle block comment
Alt+Z 切换换行 Toggle word wrap