《Go语言核心36讲》笔记2:Golang工作区和GOPATH

安装

一般都是从官网下载二进制包(由于特殊原因,国内一般都是从https://studygolang.com/ 下载),然后解压缩包,放置目录,配置环境变量,通过命令:

go version

来验证下是否安装成功。

环境变量介绍

GOROOT:Golang的安装路径

GOPATH:可以理解为工作目录或者工作区,也是平时接触最多的一个变量。它可以是一个目录,可以是多个目录路径,每个目录代表一个工作区。

这些目录用于放置Go语言的源码文件(src),以及安装(命令go install)后的归档文件(pkg目录)和可执行文件(bin目录)

GOBIN:GOROOT目录下的可执行文件放置目录,一般指bin。

解释一下什么是归档文件:就是分类,linux中就是把一些文件放在一个包中归类,一般扩展名为“.a”,意思是archive。在C程序中也指程序编译后生成的静态库文件。

问题

设置GOPATH有什么意义?

解析

Go的所有操作(编码、依赖管理、构建、测试、安装等)基本上都是围绕GOPATH来进行的。

最好去深入了解一下Go的构建和安装过程,比如Go build命令的一些可选项的用途和方法:

usage: go build [-o output] [-i] [build flags] [packages]

Build compiles the packages named by the import paths,
along with their dependencies, but it does not install the results.

If the arguments to build are a list of .go files, build treats
them as a list of source files specifying a single package.

When compiling a single main package, build writes
the resulting executable to an output file named after
the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe')
or the source code directory ('go build unix/sam' writes 'sam' or 'sam.exe').
The '.exe' suffix is added when writing a Windows executable.

When compiling multiple packages or a single non-main package,
build compiles the packages but discards the resulting object,
serving only as a check that the packages can be built.

When compiling packages, build ignores files that end in '_test.go'.

The -o flag, only allowed when compiling a single package,
forces build to write the resulting executable or object
to the named output file, instead of the default behavior described
in the last two paragraphs.

The -i flag installs the packages that are dependencies of the target.

The build flags are shared by the build, clean, get, install, list, run,
and test commands:

        -a
                force rebuilding of packages that are already up-to-date.
        -n
                print the commands but do not run them.
        -p n
                the number of programs, such as build commands or
                test binaries, that can be run in parallel.
                The default is the number of CPUs available.
        -race
                enable data race detection.
                Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
        -msan
                enable interoperation with memory sanitizer.
                Supported only on linux/amd64,
                and only with Clang/LLVM as the host C compiler.
        -v
                print the names of packages as they are compiled.
        -work
                print the name of the temporary work directory and
                do not delete it when exiting.
        -x
                print the commands.

        -asmflags '[pattern=]arg list'
                arguments to pass on each go tool asm invocation.
        -buildmode mode
                build mode to use. See 'go help buildmode' for more.
        -compiler name
                name of compiler to use, as in runtime.Compiler (gccgo or gc).
        -gccgoflags '[pattern=]arg list'
                arguments to pass on each gccgo compiler/linker invocation.
        -gcflags '[pattern=]arg list'
                arguments to pass on each go tool compile invocation.
        -installsuffix suffix
                a suffix to use in the name of the package installation directory,
                in order to keep output separate from default builds.
                If using the -race flag, the install suffix is automatically set to race
                or, if set explicitly, has _race appended to it. Likewise for the -msan
                flag. Using a -buildmode option that requires non-default compile flags
                has a similar effect.
        -ldflags '[pattern=]arg list'
                arguments to pass on each go tool link invocation.
        -linkshared
                link against shared libraries previously created with
                -buildmode=shared.
        -pkgdir dir
                install and load all packages from dir instead of the usual locations.
                For example, when building with a non-standard configuration,
                use -pkgdir to keep generated packages in a separate location.
        -tags 'tag list'
                a space-separated list of build tags to consider satisfied during the
                build. For more information about build tags, see the description of
                build constraints in the documentation for the go/build package.
        -toolexec 'cmd args'
                a program to use to invoke toolchain programs like vet and asm.
                For example, instead of running asm, the go command will run
                'cmd args /path/to/asm <arguments for asm>'.

The -asmflags, -gccgoflags, -gcflags, and -ldflags flags accept a
space-separated list of arguments to pass to an underlying tool
during the build. To embed spaces in an element in the list, surround
it with either single or double quotes. The argument list may be
preceded by a package pattern and an equal sign, which restricts
the use of that argument list to the building of packages matching
that pattern (see 'go help packages' for a description of package
patterns). Without a pattern, the argument list applies only to the
packages named on the command line. The flags may be repeated
with different patterns in order to specify different arguments for
different sets of packages. If a package matches patterns given in
multiple flags, the latest match on the command line wins.
For example, 'go build -gcflags=-S fmt' prints the disassembly
only for package fmt, while 'go build -gcflags=all=-S fmt'
prints the disassembly for fmt and all its dependencies.

For more about specifying packages, see 'go help packages'.
For more about where packages and binaries are installed,
run 'go help gopath'.
For more about calling between Go and C/C++, run 'go help c'.

Note: Build adheres to certain conventions such as those described
by 'go help gopath'. Not all projects can follow these conventions,
however. Installations that have their own conventions or that use
a separate software build system may choose to use lower-level
invocations such as 'go tool compile' and 'go tool link' to avoid
some of the overheads and design decisions of the build tool.

See also: go install, go get, go clean.

知识扩展

Go语言源代码的组织方式

扫描二维码关注公众号,回复: 2758128 查看本文章

Go语言的源码是以代码包为基本组织单位的。在文件系统中,与目录一一对应,目录可以有子目录,代码包可以有子包。

一个代码包可以包含任意个以.go为扩展名的源码,这些源码文件都需要被声明为属于同一个代码包。

代码包的名称一般会与这些源码文件所在的目录同名,如果不同名,那么在构建、安装的过程中会以代码包名称为准。

代码包需要导入才能使用,如:

import 'github.com/labstack/echo'

在工作区中,一个代码包的导入路径实际上就是src子目录,到该包的实际存储位置的相对路径。

链接源码安装后的结果

源码会放在工作区的src目录。

安装后产生的归档文件放在pkg目录,如果产生了可执行文件(命令源码编译),可能会放进bin子目录。

源码文件以代码包的形式组织,一个代码包就对应一个目录。安装某个代码包而产生的归档文件与这个代码包同名,比如,一个已存在的代码包的导入路径是:github.com/labstack/echo,那么执行安装命令:

go install github.com/labstack/echo

生成的归档文件的相对目录、子目录的名称就是:github.com/labstack,文件名为echo.a。

路径解析:该代码包的源码文件存在于 github 网站 labstack 组的 echo 仓库中。

补充说明:在归档文件的相对目录与pkg目录之间,还有一级目录,叫做平台相关目录,其名称是由build(构建)的目标操作系统+下划线+目标计算架构的代号一起组合而成,例如,构建某个代码包的目标操作系统是Linux,目标计算架构是64位,那么对应的平台相关目录就是linux_amd64,上述代码包的归档文件会被放置在当前工作区的子目录:pkg/linux_amd64/github.com/labstack中。

理解构建和安装Go的过程

构建使用命令:go build

安装使用命令:go install

两者都会执行编译、打包等操作,并且会生成一些临时文件。

如果构建的是库源码文件,那么操作的结果文件只会存在于临时目录中(不会到目标目录),所以主要意义在于检查和验证。

如果构建的是命令源码文件,那么操作的结果文件会被存储到源码文件所在的目录中(生成可执行文件)。

安装操作包含了构建操作,然后进行链接操作,并把结果文件搬运到指定目录。如果安装的是库源码文件(比如从github上下载的库文件),那么结果文件会被搬运到工作区的pkg目录中的子目录中(如github.com/google/)。

如果安装的是命令源码文件(执行文件),那么结果文件会被搬运到它所在工作区的bin目录或者环境变量GOBIN指向的目录。

Go build命令的一些用法

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

那么,如果要强制编译的话,可以在执行命令的时候加入标记 -a,如:

go build -a

这个时候,目标代码包和以来代码包都会被强制编译。

如果要同时安装他们的归档文件(定义见文前),那么可以加入标记-i,如:

go build -i

有两种方法可以查看哪些代码包被编译了:

1、加标记 -x,可以显示go build命令执行了哪些操作;加标记 -n,可以只查看具体操作而不执行。

2、加入标记-v,可以查看编译代码包的名称,最好与-a搭配起来使用(见前文)

Go get介绍

该命令自动从一些主流公用代码仓库下载目标代码包,并安装到GOPATH的第一个工作区。如果存在环境变量GOBIN(见前文),那么仅包含命令源码文件的代码文件包会被安装到GOBIN指向的那个目录

Go get常用标记
-u 下载并安装代码包,如果工作区已有,则覆盖
-d 只下载代码包,不安装
-fix 在下载代码包后,先运行一个Go语言版本修正代码的工具,待检查无误,然后在安装代码包。
-t 同时下载测试所需的代码包
-insecure 允许通过http协议下载和安装代码包

一些第三方(如glide,gb出品的dep,vgo)工具也提供了依赖管理的功能,补充go get的不足,但是它们内部还是使用go get命令。

自定义代码包导入路径

用于变更存储源码的代码仓库或者代码包的相对路径,使用方法:

package semaphore // import 'golang.org/x/sync/semaphore'

这个代码包原本导入路径是:github.com/golang/sync/semaphore,而实际是存储在golang.org组的sync代码仓库的semaphore目录下。这个时候,可以加入上述的导入注释安装代码包:

go get golang.org/x/sync/semaphore

而其实golang.org下的路径/x/sync/semaphore其实并不存在,这就是自定义导入路径。

要注意的是,这需要服务端程序的支持,比如在golang.org上增加路由转换。

举例说明:

先使用 go get 命令下载go_spider源码:

go get github.com/hu17889/go_spider

然后编译安装命令源文件(main函数入口):

go install github.com/hu17889/go_spider/example/github_repo_page_processor

安装完成后,会在工作区目录的bin下,产生一个可执行文件,你可以直接运行:

bin/github_repo_page_processor.exe

输出执行结果:

2018/08/14 10:19:15 ** start spider **
2018/08/14 10:19:15 start crawl : https://github.com/hu17889?tab=repositories
2018/08/14 10:19:17 ** executed callback **
TODO:before end spider
2018/08/14 10:19:17 ** end spider **

总结

要深刻理解GOPATH的概念和含义,也是Go程序开发的核心知识。

Go语言的很多工具,例如go build、go install、go get都是在GOPATH和工作区的基础上运行的。

思考题

  1. Go语言在多个工作区中查找依赖包的时候,是以怎样的顺序进行的?
  2. 如果在多个工作区中都存在导入路径相同的代码包会产生冲突吗?

实践出真理,最好是做几个试验检验一下。

另外,看一下Go语言标准库中Go build包及其子包的源码,也可以加深理解。

猜你喜欢

转载自blog.csdn.net/apanious/article/details/81627302