GO语言基础篇(三)- 一文吃透GO常用命令

1,288 阅读15分钟

这是我参与8月更文挑战的第 3 天,活动详情查看: 8月更文挑战

本文主要分享go语言中一些常用的命令,包括使用、命令底层执行过、区别等。预了解本部分内容,需要对go源码文件的分类及代码包有一定的了解,如果你也是新手,可以先移步这里

GO常用命令详解

查看go全部命令

可以通过以下命令来查看go的命令有哪些,以及每个命令的含义

执行:go help

结果打印:

Usage:

	go <command> [arguments]

The commands are:

	bug         start a bug report  打开错误报告
	build       compile packages and dependencies  //编译包和依赖
	clean       remove object files and cached files  //删除目标文件和缓存文件
	doc         show documentation for package or symbol //打印附于Go语言程序实体上的文档(在非 main 包下,执行 go doc 打印当前代码包文档及其程序实体列表(程序实体:变量、常量、函数、结构体以及接口))
	env         print Go environment information //打印go环境变量信息
	fix         update packages to use new APIs  //更新包以使用新的API
	fmt         gofmt (reformat) package sources //格式化代码文件(Go语言的开发团队制定了统一的官方代码风格,并且推出了 gofmt 工具(gofmt 或 go fmt)来帮助开发者格式化他们的代码到统一的风格)
	generate    generate Go files by processing source //go generate命令是在Go语言 1.4 版本里面新添加的一个命令,当运行该命令时,它将扫描与当前包相关的源代码文件,找出所有包含//go:generate的特殊注释,提取并执行该特殊注释后面的命令
	get         download and install packages and dependencies  //下载并安装软件包和依赖项
	install     compile and install packages and dependencies //编译和安装包和依赖项
	list        list packages or modules  //列出包或模块
	mod         module maintenance //模块管理
	run         compile and run Go program  //编译和运行一个go程序
	test        test packages //测试包
	tool        run specified go tool // 运行指定的 go 工具
	version     print Go version //打印go的版本信息
	vet         report likely mistakes in packages // 报告包中可能存在的错误

查看go指定命令的用法

方法:go help 命令名称(以env命令为例)
执行:go help env
打印结果:

usage: go env [-json] [-u] [-w] [var ...]

Env prints Go environment information.

By default env prints information as a shell script
(on Windows, a batch file). If one or more variable
names is given as arguments, env prints the value of
each named variable on its own line.

The -json flag prints the environment in JSON format
instead of as a shell script.

The -u flag requires one or more arguments and unsets
the default setting for the named environment variables,
if one has been set with 'go env -w'.

The -w flag requires one or more arguments of the
form NAME=VALUE and changes the default settings
of the named environment variables to the given values.

For more about environment variables, see 'go help environment'.

常用命令详解

虽然go的命令有十几个,但是我们最常用到的并没有几个,下边下详细介绍:go build、go get、go install、go run,这四个最常用的命令

四个常用命令的通用参数

  • -a:用于强制重新编译所有涉及的Go语言代码包(包括 Go 语言标准库中的代码包),即使它们已经是最新的了。该标记可以让我们有机会通过改动底层的代码包做一些实验。假设我有一个命令源码,它里边导入了代码包A,而这个代码包A,我之前编译过,并且编译之后,A这个源码包中的代码,没有产生任何的变化,go run命令在不加任何参数的默认情况下,是不会再次编译它的,但是加上-a参数之后,会再次它们,即使他们的归档文件已经存在,并且已经是最新的
  • -n仅打印其执行过程中用到的所有命令,而不去真正执行它们。如果只想查看或者验证命令的执行过程,而不想改变任何东西(不想产生任何后果),使用它正好合适
  • -p n:该命令是go run特有的。并行编译,其中n为并行的数量。现在已经是多核时代,我们的计算机可能有多个CPU,或者我们的计算机有多个核,这个并行编译的标记,会使go run命令的编译操作更加迅速。这个n的值,最好设置成当前计算机的逻辑CPU个数。假设我们的计算机有两个CPU,每个CPU有两个核,那么这台计算机的逻辑CPU就是4
  • -v用于打印命令执行过程中涉及的代码包(列出被编译的代码包名称) 。包括我们指定的目标代码包,并且有时还会包括该代码包直接或间接依赖的那些代码包。这会让你知道哪些代码包被执行过了。注意:在go的1.3版本中,-v参数打印出来的代码包,包含go语言自带的标准库的代码包。但是,在go的1.4版本中,-v参数打印出来的代码包,不包含go语言自带的标准库的代码包(就算我们导入了go标准库的代码包,使用-v参数,也不会打印出来)
  • -work用于打印命令执行时生成和使用的临时工作目录的名字,且命令执行完成后不删除它。这个目录下的文件可能会对你有用,也可以从侧面了解命令的执行过程。如果不添加此标记,那么临时工作目录会在命令执行完毕前删除
  • -x:打印编译过程中用到的所有命令,并同时执行它们。(而-n参数是不真正执行它们)
  • -race用于检测并报告指定 Go 语言程序中存在的数据竞争问题。当用 Go 语言编写并发程序的时候,这是很重要的检测手段之一

下边在介绍go的具体命令时,会展示各个参数的使用及效果

go run

go run是专门用来运行命令源码文件的命令。并不是用来运行所有的go源码文件的

go run 命令只能接受一个命令源码文件以及若干个库源码文件(必须同属于 main 包)作为文件参数,且不能接受测试源码文件。这也就是说,go run命令后边可以跟多个源码文件,但其中只能有一个命令源码文件

go run命令内部的操作步骤

它会先编译作为文件参数的源码文件,将他们的编译结果,放到一个临时文件夹中,然后再去运行这个编译的结果,这个编译结果包括命令源码文件被编译后生成的可执行文件 以及 相关库源码文件编译后生成的归档文件(可能不太容易理解这段话,往下看示例)

下边通过代码示例来演示各个参数的作用及效果

在我的工作目录下有一个命令源码文件study.go,内容如下
package main

import "fmt"

func main()  {
	fmt.Println("Just a test")
}

-n参数演示

使用-n参数来看编译执行一个命令源码文件过程中用到的命令

执行:go run -n study.go

打印结果:
#
# command-line-arguments
#

mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg << 'EOF' # internal
# import config
packagefile fmt=/usr/local/go/pkg/darwin_amd64/fmt.a
packagefile runtime=/usr/local/go/pkg/darwin_amd64/runtime.a
EOF
cd /Users/shulv/studySpace/GolangProject/src/entry
/usr/local/go/pkg/tool/darwin_amd64/compile -o $WORK/b001/_pkg_.a -trimpath "$WORK/b001=>" -p main -complete -buildid OZxgjhaidDSIEHCDtqvJ/OZxgjhaidDSIEHCDtqvJ -dwarf=false -goversion go1.16.6 -D _/Users/shulv/studySpace/GolangProject/src/entry -importcfg $WORK/b001/importcfg -pack -c=4 ./study.go
/usr/local/go/pkg/tool/darwin_amd64/buildid -w $WORK/b001/_pkg_.a # internal
cat >$WORK/b001/importcfg.link << 'EOF' # internal
packagefile command-line-arguments=$WORK/b001/_pkg_.a
packagefile fmt=/usr/local/go/pkg/darwin_amd64/fmt.a

......

packagefile internal/race=/usr/local/go/pkg/darwin_amd64/internal/race.a
packagefile path=/usr/local/go/pkg/darwin_amd64/path.a
EOF
mkdir -p $WORK/b001/exe/
cd .
/usr/local/go/pkg/tool/darwin_amd64/link -o $WORK/b001/exe/study -importcfg $WORK/b001/importcfg.link -s -w -buildmode=exe -buildid=445UgZBfJLTSQgITptfl/OZxgjhaidDSIEHCDtqvJ/OZxgjhaidDSIEHCDtqvJ/445UgZBfJLTSQgITptfl -extld=clang $WORK/b001/_pkg_.a
$WORK/b001/exe/study

执行结果看起来好像很乱,但实际上,它做了以下几件事

  1. 创建一个临时目录b001:mkdir -p WORK/b001/(这个WORK/b001/(这个WORK不知道对应的是哪个路径没关系,别忘了我们还有-work参数,可以打印生成的临时工作目录)
  2. 查找依赖信息:cat >$WORK/b001/importcfg << ...
  3. 执行源代码编译:/usr/local/go/pkg/tool/darwin_amd64/compile -o ...
  4. 收集链接库文件:cat >$WORK/b001/importcfg.link << ...
  5. 在b001中创建临时目录exe:mkdir -p $WORK/b001/exe/
  6. 生成可执行文件:/usr/local/go/pkg/tool/darwin_amd64/link -o ...
  7. 运行可执行文件

从结果中可以看出来,-n参数只打印了过程中所使用到的命令,并没有真正的执行,因为最后在执行可执行文件的时候,并没有将”Just a test“给打印出来

-work参数演示

使用-work参数,打印出执行过程中生成的临时工作目录

执行:go run -work study.go

打印结果:
WORK=/var/folders/v2/8n4xnrln7l34q18v_2dt6tdr0000gn/T/go-build1801219739
Just a test

可以看到结果中展示了临时目录的路径 和 源码文件的执行结果。因为使用-work参数之后,临时目录不会被删除,所以我们可以到这个临时目录中看其结构

临时目录路径:/var/folders/v2/8n4xnrln7l34q18v_2dt6tdr0000gn/T/go-build1801219739
目录结构:
.
└── b001
    ├── _pkg_.a
    ├── exe
    │   └── study
    ├── importcfg
    └── importcfg.link

-a参数演示

-a参数用于强制重新编译所有涉及的Go语言代码包(包括 Go 语言标准库中的代码包),即使它们已经是最新的了

上边我们已经对study.go文件编译执行过一次了,并且没有对文件内容进行修改。如果我们不使用-a参数,而是直接执行go run,它将不会再次执行编译过程,而是直接链接后执行。下边借助-n参数来证明一下

在源码文件没有被修改的情况下,再次执行:go run -n study.go

打印结果:
go run -n study.go 
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg.link << 'EOF' # internal
packagefile command-line-arguments=/Users/shulv/Library/Caches/go-build/d9/d98055ba422899604fd059aa39fc27972585449930cdd8fc3858b6149a749b27-d
packagefile fmt=/usr/local/go/pkg/darwin_amd64/fmt.a

......

packagefile internal/race=/usr/local/go/pkg/darwin_amd64/internal/race.a
packagefile path=/usr/local/go/pkg/darwin_amd64/path.a
EOF
mkdir -p $WORK/b001/exe/
cd .
/usr/local/go/pkg/tool/darwin_amd64/link -o $WORK/b001/exe/study -importcfg $WORK/b001/importcfg.link -s -w -buildmode=exe -buildid=A5ZhwB9IgatL5rEMAAB6/OZxgjhaidDSIEHCDtqvJ/jKFA8Xft5BKXCFiDMFrC/A5ZhwB9IgatL5rEMAAB6 -extld=clang /Users/shulv/Library/Caches/go-build/d9/d98055ba422899604fd059aa39fc27972585449930cdd8fc3858b6149a749b27-d
$WORK/b001/exe/study

因为不加-work参数,在每次编译执行的后,会将临时目录删除,所以我们每次在执行go run的时候,它都会先创建临时目录,所以我们看到了:mkdir -p $WORK/b001/。然后我们看到查找完依赖之后,它接着创建了临时目录exe,后边就直接执行了link操作,最后执行了可执行文件。中间没有了编译操作

此时你可以在保证源文件没有修改的情况下,加上-a参数,会发现此时源文件被强制编译了,哪怕源文件没有修改(我这里就不再贴执行结果了)

-x参数演示

-x打印编译过程中用到的所有命令,并执行

执行:go run -x study.go

打印结果:

WORK=/var/folders/v2/8n4xnrln7l34q18v_2dt6tdr0000gn/T/go-build168647433
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg.link << 'EOF' # internal
packagefile command-line-arguments=/Users/shulv/Library/Caches/go-build/0a/0a84b98e4a2edf7cf6661ae1c30d9abe59977dff84f8a95dc3527499292fd168-d
packagefile studygo=/Users/shulv/Library/Caches/go-build/b8/b826e18cb44b50e651c70cd14a931a1ed5e8e7669f7340c31b947ac8043787c4-d
packagefile runtime=/usr/local/go/pkg/darwin_amd64/runtime.a
......
packagefile internal/race=/usr/local/go/pkg/darwin_amd64/internal/race.a
packagefile path=/usr/local/go/pkg/darwin_amd64/path.a
EOF
mkdir -p $WORK/b001/exe/
cd .
/usr/local/go/pkg/tool/darwin_amd64/link -o $WORK/b001/exe/study -importcfg $WORK/b001/importcfg.link -s -w -buildmode=exe -buildid=POnNYYqFpCxtCoPh1xl9/_rKHpBsVyWow7NdS85MK/3k-oIa2YhBkHW0aWVSoW/POnNYYqFpCxtCoPh1xl9 -extld=clang /Users/shulv/Library/Caches/go-build/0a/0a84b98e4a2edf7cf6661ae1c30d9abe59977dff84f8a95dc3527499292fd168-d
$WORK/b001/exe/study
Just a test

可以看到输出了整个编译运行过程中执行过的命令,并打印出了命令源码文件的执行结果

综上:go run的执行过程就是:源码 ==》编译 ==》连接 ==》可执行文件==》执行输出

image.png

图片来源:初探 Go 的编译命令执行过程

go build

go build 用于编译我们指定的源码文件或代码包以及它们的依赖包go build完成了源码的编译与可执行文件的生成。go build接收参数为.go文件或目录,默认情况下编译当前目录下所有.go文件

go build命令用法

  • 如果go build后边跟的是一个命令源码文件,会在当前目录下生成一个可执行文件。如果想在$GOPATH/bin目录下生成相应的可执行文件,需要执行go install(后边会介绍这个命令)或者使用 go build -o 路径/可执行文件名称(如果使用go install命令需要注意:如果 GOPATH 里面只有一个工作区,就会在当前工作区的 bin 目录下生成相应的可执行文件。如果 GOPATH 下有多个工作区,则是在 GOBIN 下生成对应的可执行文件
  • 如果go build后边跟的是一个库源码文件,它只是检查库源码文件的有效性,只会做检查性的编译,而不会输出任何结果文件
  • 如果仅使用go build,后边不跟任何参数,或者后边跟代码包导入路径,那么代码包中所有的go文件都会被编译(但是,go build 会忽略目录下以”_”或者”.”开头的go文件
  • go build 既不能编译包含多个命令源码文件的代码包,也不能同时编译多个命令源码文件。因为如果把多个命令源码文件作为一个整体看待,那么每个文件中的main函数都属于重名函数,在编译时会抛出重复定义错误

go build命令使用演示

  1. go build 命令源码文件
目录结构 & 文件内容  还是和上边的示例一样
├── bin
├── pkg
└── src
    ├── entry
    │   └── study.go // 命令源码文件
    └── studygo
        └── learnGo.go // 库源码文件

在entry目录下执行:go build study.go
执行完之后,终端上不会有任何输出,此时看一下目录结构
├── bin
├── pkg
└── src
    ├── entry
    │   ├── study //新生成的可执行文件
    │   └── study.go
    └── studygo
        └── learnGo.go
  1. go build 库源码文件

进入到studygo目录下执行:go build learnGo.go。不会生成任何文件,现在可能看不出什么,后边在介绍go build的执行过程时,就会明白,执行这个命令之后,发生了什么

  1. go build

直接在一个代码包下执行go build,后边不跟任何参数

先删除刚才生成的study可执行文件,然后进入到entry目录执行:go build

打印结果:
├── bin
├── pkg
└── src
    ├── entry
    │   ├── entry //新生成的可执行文件
    │   └── study.go
    └── studygo
        └── learnGo.go

相信聪明的你已经发现,如果go build后跟命令源码文件时,生成的的可执行文件名和命令源码文件一样,如果单纯执行go build,生成的可执行文件和当前代码包的名称是一样的

在上边提到的公共参数,在go build中也是适用的,含义相同

go build命令执行过程

可以利用上边提到的-n参数,来查看go build 在执行过程中都做了些什么

go build编译命令源码文件过程

进入到entry目录下执行:go build -n study.go

打印结果:

#
# command-line-arguments
#

mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg << 'EOF' # internal
# import config
packagefile fmt=/usr/local/go/pkg/darwin_amd64/fmt.a
packagefile runtime=/usr/local/go/pkg/darwin_amd64/runtime.a
EOF
cd /Users/shulv/studySpace/GolangProject/src/entry
/usr/local/go/pkg/tool/darwin_amd64/compile -o $WORK/b001/_pkg_.a -trimpath "$WORK/b001=>" -p main -complete -buildid aPJghGhqw4j27W2678s0/aPJghGhqw4j27W2678s0 -goversion go1.16.6 -D _/Users/shulv/studySpace/GolangProject/src/entry -importcfg $WORK/b001/importcfg -pack -c=4 ./study.go
/usr/local/go/pkg/tool/darwin_amd64/buildid -w $WORK/b001/_pkg_.a # internal
cat >$WORK/b001/importcfg.link << 'EOF' # internal
packagefile command-line-arguments=$WORK/b001/_pkg_.a
......
packagefile internal/race=/usr/local/go/pkg/darwin_amd64/internal/race.a
packagefile path=/usr/local/go/pkg/darwin_amd64/path.a
EOF
mkdir -p $WORK/b001/exe/
cd .
/usr/local/go/pkg/tool/darwin_amd64/link -o $WORK/b001/exe/a.out -importcfg $WORK/b001/importcfg.link -buildmode=exe -buildid=ZnGlctoVozInY7SAxZMW/aPJghGhqw4j27W2678s0/aPJghGhqw4j27W2678s0/ZnGlctoVozInY7SAxZMW -extld=clang $WORK/b001/_pkg_.a
/usr/local/go/pkg/tool/darwin_amd64/buildid -w $WORK/b001/exe/a.out # internal
mv $WORK/b001/exe/a.out study

可以发现,跟go run命令的执行过程几乎一样,不一样的地方就是在最下边一行。go run执行了生成的可执行文件,而go build 命令是把可执行文件移动到了当前目录的文件夹中

我们可以通过-work参数来获取到生成的临时目录路径,然后看一下和go run生成的有何不同

这里展示一下我执行go build -work study.go,生成的临时目录结构
.
└── b001
    ├── _pkg_.a
    ├── exe
    ├── importcfg
    └── importcfg.link

会发现,和go run执行之后相比,exe目录下没了可执行文件。原因就是go build执行之后,将可执行文件移到当前目录下了

可以发现,go build编译命令源码文件的过程就是:命令源码文件 ==》 编译 ==》链接 ==》可执行文件

go build编译库源码文件过程

进入studygo目录,执行:go build -n learnGo.go

#
# command-line-arguments
#

mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg << 'EOF' # internal
# import config
packagefile fmt=/usr/local/go/pkg/darwin_amd64/fmt.a
EOF
cd /Users/shulv/studySpace/GolangProject/src/studygo
/usr/local/go/pkg/tool/darwin_amd64/compile -o $WORK/b001/_pkg_.a -trimpath "$WORK/b001=>" -p command-line-arguments -complete -buildid WkKm9j3sTnSZXyJlO623/WkKm9j3sTnSZXyJlO623 -goversion go1.16.6 -D _/Users/shulv/studySpace/GolangProject/src/studygo -importcfg $WORK/b001/importcfg -pack -c=4 ./learnGo.go
/usr/local/go/pkg/tool/darwin_amd64/buildid -w $WORK/b001/_pkg_.a # internal

可以看到 go build 命令只是把库源码文件编译了一遍,其他什么事情都没有干。所以go build编译库源码文件的过程是:库源码文件 ==》 编译 。很明显,此时go build的作用就是测试库源码文件能否正常编译,用来测试编译

image.png

图片来源:初探 Go 的编译命令执行过程

go install

go install 命令是用来编译并安装代码包或者源码文件的

go install命令用法

当指定的代码包的依赖包还没有被编译和安装时,该命令会先去处理依赖包。与 go build 命令一样,传给 go install 命令的代码包参数应该以导入路径的形式提供。并且,go build 命令的绝大多数标记也都可以用于 go install 命令。实际上,go install 命令只比 go build 命令多做了一件事,即:安装编译后的结果文件到指定目录

  • 安装代码包会在当前工作区的 pkg 的平台相关目录下生成归档文件(即 .a 文件)
  • 安装命令源码文件会在当前工作区的 bin 目录(如果 GOPATH 下有多个工作区,就会放在 GOBIN 目录下)生成可执行文件
  • go install 命令如果后面不追加任何参数,它会把当前目录作为代码包并安装。这和 go build 命令是完全一样的
  • go install 命令后面如果跟了代码包导入路径作为参数,那么该代码包及其依赖都会被安装
  • go install 命令后面如果跟了命令源码文件以及相关库源码文件作为参数的话,只有这些被指定的文件会被编译并安装

go install命令使用演示

go install 命令源码文件

执行:go install study.go

执行完之后,看目录结构变化
.
├── bin
│   └── study //新生成的可执行文件
├── pkg
└── src
    ├── entry
    │   └── study.go
    └── studygo
        └── learnGo.go

go install 库源码文件

执行:go install

执行完之后,看目录结构变化:
.
├── bin
│   └── study
├── pkg
│   └── darwin_amd64
│       └── studygo.a //新生成的归档文件
└── src
    ├── entry
    │   └── study.go
    └── studygo
        └── learnGo.go

go install命令执行过程

这里不再逐一展示go install编译安装命令源码文件和库源码文件的过程了,大家可以自己动手试试。我这里直接给出结论

  • go install编译安装命令源码文件的过程和go build相比,多了最后一步,go install 会把编译命令源码文件生成的可执行文件安装到当前工作区的 bin 目录(如果 GOPATH 下有多个工作区,就会放在 GOBIN 目录下)
  • go install编译安装库源码文件的过程和go build相比,go install 会把编译库源码文件生成的归档文件安装到当前工作区的 pkg 目录

image.png

图片来源:初探 Go 的编译命令执行过程

go get

go get 命令会自动从主流公用代码仓库下载代码包(比如github),它会把当前的代码包下载到 $GOPATH 中的第一个工作区的 src 目录中,并安装

go get支持的代码版本控制系统有:Git、SVN、Mercurial(hg)、Bazaar

go get 命令常用参数

  • -d让命令程序只执行下载动作,而不执行安装动作。有些非常特殊的代码包在安装过程中需要有特殊的处理,我们需要先下载下来,暂时不进行安装动作,此时就可以用-d参数
  • -u加该参数可利用网络来更新已有代码包及其依赖包默认情况下,该命令只会从网络上下载本地不存在的代码包,而不会更新已有的代码包。如果已经下载过一个代码包,但是这个代码包又有更新了,那么这时候可以直接用-u参数来更新本地的对应的代码包。如果不加这个-u参数,执行 go get 命令获取一个已有的代码包,会发现命令什么都不执行。只有加了-u参数,命令才会去执行 git pull 命令拉取最新的代码包的最新版本,下载并安装
  • -f仅在使用-u标记时才有效。该标记会让命令程序忽略掉对已下载代码包的导入路径的检查。如果下载并安装的代码包所属的项目是你从别人那里 Fork 过来的,那么这样做就尤为重要了
  • -t让命令程序同时下载并安装指定的代码包中的测试源码文件中依赖的代码包
  • -fix:让命令程序在下载代码包后先执行修正动作,而后再进行编译和安装
  • -insecure允许命令程序使用非安全的 scheme(如 HTTP )去下载指定的代码包。如果你用的代码仓库(如公司内部的 Gitlab )没有HTTPS 支持,可以添加此标记。请在确定安全的情况下使用它

这里说明一下-fix参数中的修正动作。比如说我们需要下载并安装的代码包,是在很早以前写的,其中使用的语法可能是go 1.0版本之前,而我们当前使用的语法时go1.4,那这其中的一些语法,以及对一些程序实体的使用方式,可能是不兼容的。为了消除这种不兼容,并可以使这个比较久远的代码包,能够被正确的编译和安装,此时就可以使用-fix参数。它会使命令程序,自动的把这些已经废弃的,或者不一样的语法语句、程序实体使用方式,修正成我们当前这个go语言版本所使用的方法和方式

go get 命令执行过程

我这里没有直接演示go get命令的每个参数的使用,大家完全可以自己按照上边其它几个命令的使用方式来自己试一下go get的各个参数的作用。下边通过通用的-x参数,来看一下go get命令的执行过程

执行:go get go get -x github.com/go-errors/errors

打印结果:

cd .
git clone -- <https://github.com/go-errors/errors> /Users/shulv/studySpace/GolangProject/src/github.com/go-errors/errors
cd /Users/shulv/studySpace/GolangProject/src/github.com/go-errors/errors
git submodule update --init --recursive
cd /Users/shulv/studySpace/GolangProject/src/github.com/go-errors/errors
git show-ref
cd /Users/shulv/studySpace/GolangProject/src/github.com/go-errors/errors
git submodule update --init --recursive
WORK=/var/folders/v2/8n4xnrln7l34q18v_2dt6tdr0000gn/T/go-build1679859398
mkdir -p $WORK/b001/
mkdir -p /Users/shulv/studySpace/GolangProject/pkg/darwin_amd64/github.com/go-errors/
cp /Users/shulv/Library/Caches/go-build/93/939c1986bb74b69ed1998e02c45b4326ba454a566c2996e5997560f8f68db355-d /Users/shulv/studySpace/GolangProject/pkg/darwin_amd64/github.com/go-errors/errors.a
rm -r $WORK/b001/

根据其执行过程可以看到,执行完 go get 命令以后,会调用 git clone 方法下载源码,并编译,最终会把库源码文件编译成归档文件安装到 pkg 对应的相关平台目录下

image.png

图片来源:初探 Go 的编译命令执行过程

感谢以下优秀文章

Go的执行原理以及Go的命令

初探 Go 的编译命令执行过程

golang 标准命令

golang 命令详解

go run go build go install 命令解释

go命令基础

GO笔记之详解GO的编译执行流程