0%

Go语言 - 01 工作区和GOPATH

Go语言的安装

参照官网文档 https://golang.org/doc/install
可以在命令行中输入命令来验证是否安装成功:

  • go version:查看安装的版本
  • go env:当前go的配置环境

2个环境变量,即 GOROOT、GOPATH和GOBIN:

  • GOROOT:go的安装路径
  • GOPATH:go的工作路径

问题 :设置 GOPATH 有什么意义?

典型回答
环境变量 GOPATH 的值可以是一个目录的路径,也可以包含多个目录路径,每个目录都代表 Go 语言的一个工作区(workspace)。
这些工作区用于放置 Go 语言的源码文件,以及安装(install)后的归档文件和可执行文件。
一个典型的workspace如下:

1
2
3
4
5
6
7
8
9
10
11
12
bin/
hello # command executable
pkg/
linux_amd64/ # this will reflect your OS and architecture
github.com/user/
stringutil.a # package object
src/
github.com/user/
hello/
hello.go # command source
stringutil/
reverse.go # package source

知识扩展

Go 语言源码的组织方式

以代码包(package)为基本组织单位的。代码包其实是与目录一一对应的。目录可以有子目录,所以代码包也可以有子包。

一个代码包中可以包含任意个以.go 为扩展名的源码文件,这些源码文件都需要被声明为属于同一个代码包。代码包的名称一般会与这些源码文件所在的目录同名。如果不同名,那么在构建、安装的过程中会以代码包名称为准。

代码包的导入:

1
import "github.com/labstack/echo"

在工作区中,一个代码包的导入路径实际上就是从 src 子目录,到该包的实际存储位置的相对路径。下面我马上就会谈到 src子目录。
插播:Go语言的源码文件有三大类,即:命令源码文件、库源码文件和测试源码文件。

构建(go build)和安装(go install)

go build: 用于编译我们指定的源码文件或代码包以及它们的依赖包。
对于只包含库源码文件的代码包, go build命令在编译时,只会做检查性的编译,操作的结果文件只会存在于临时目录中,立刻自动删除,而不会输出任何结果文件。
如果想保留在临时工作目录,不删除掉:

1
2
➜  stringutil go build -work
WORK=/var/folders/5s/25ck5pv16rg55hr2kfdvtszc0000gp/T/go-build412712988

如果构建的是命令源码文件,那么操作的结果文件会被搬运到那个源码文件所在的目录中。

1
2
3
4
5
➜  hello git:(master) ✗ ls
hello.go
➜ hello git:(master) ✗ go build
➜ hello git:(master) ✗ ls
hello hello.go

go install: 安装操作会先执行构建(go build),然后还会进行链接操作,并且把结果文件搬运到指定目录。
进一步说,如果安装的是库源码文件,那么结果文件会被搬运到它所在工作区的 pkg 目录下的某个子目录中。

1
2
3
4
➜  XuSenqi ls /Users/patrick.xu/go/pkg/darwin_amd64/github.com/XuSenqi
➜ XuSenqi go install github.com/XuSenqi/stringutil
➜ XuSenqi ls /Users/patrick.xu/go/pkg/darwin_amd64/github.com/XuSenqi
stringutil.a

如果安装的是命令源码文件,那么结果文件会被搬运到它所在工作区的 bin 目录中,或者环境变量GOBIN指向的目录中。同时,依赖的代码包也会安装到pgk下对应的目录中。

1
2
3
4
5
6
7
8
➜  XuSenqi ls /Users/patrick.xu/go/pkg/darwin_amd64/github.com/XuSenqi
➜ XuSenqi ls /Users/patrick.xu/go/bin/hello
ls: /Users/patrick.xu/go/bin/hello: No such file or directory
➜ XuSenqi go install github.com/XuSenqi/hello/
➜ XuSenqi ls /Users/patrick.xu/go/pkg/darwin_amd64/github.com/XuSenqi
stringutil.a
➜ XuSenqi ls /Users/patrick.xu/go/bin/hello
/Users/patrick.xu/go/bin/hello

go build 命令一些可选项的用途和用法

在运行go build命令的时候,默认不会编译目标代码包所依赖的那些代码包。当然,如果被依赖的代码包的归档文件不存在,或者源码文件有了变化,那它还是会被编译。

如果要强制编译它们,可以在执行命令的时候加入标记-a。此时,不但目标代码包总是会被编译,它依赖的代码包也总会被编译,即使依赖的是标准库中的代码包也是如此。

表1 go build命令的常用标记说明

标记名称 标记描述
-a 强行对所有涉及到的代码包(包含标准库中的代码包)进行重新构建,即使它们已经是最新的了。
-n 打印编译期间所用到的其它命令,但是并不真正执行它们。
-p n 指定编译过程中执行各任务的并行数量(确切地说应该是并发数量)。在默认情况下,该数量等于CPU的逻辑核数。但是在darwin/arm平台(即iPhone和iPad所用的平台)下,该数量默认是1。
-race 开启竞态条件的检测。不过此标记目前仅在linux/amd64、freebsd/amd64、darwin/amd64和windows/amd64平台下受到支持。
-v 打印出那些被编译的代码包的名字。
-work 打印出编译时生成的临时工作目录的路径,并在编译结束时保留它。在默认情况下,编译结束时会删除该目录。
-x 打印编译期间所用到的其它命令。注意它与-n标记的区别。

go get

go get可以根据要求和实际情况从互联网上下载或更新指定的代码包及其依赖包,并对它们进行go build和go install。

1
2
3
4
5
➜  XuSenqi go get github.com/hyper-carrot/go_lib/logging
➜ XuSenqi ls $GOPATH/src/github.com/hyper-carrot/go_lib/logging
base.go console_logger.go log_manager.go logger_test.go tag.go
➜ XuSenqi ls /Users/patrick.xu/go/pkg/darwin_amd64/github.com/hyper-carrot/go_lib/logging.a
/Users/patrick.xu/go/pkg/darwin_amd64/github.com/hyper-carrot/go_lib/logging.a

表2 go get命令的常用标记说明

标记名称 标记描述
-d 让命令程序只执行下载动作,而不执行安装动作。
-u 让命令利用网络来更新已有代码包及其依赖包。默认情况下,该命令只会从网络上下载本地不存在的代码包,而不会更新已有的代码包。

参考

go build
http://wiki.jikexueyuan.com/project/go-command-tutorial/0.1.html
go get
http://wiki.jikexueyuan.com/project/go-command-tutorial/0.3.html
https://github.com/hyper0x/go_command_tutorial/blob/master/0.3.md