这是我参与「第五届青训营 」笔记创作活动的第3天
前言:
最近学go语法,碰见许多包导入的问题,之前先学的语法,现在来补补基础。Go的依赖管理和java一样,可大可小,得养成一个好习惯,本文先记录一下环境的基础问题。
一. Go环境变量信息
图片来源网络
控制台输入go env,可以查看如下信息:
$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/davy/go"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
命令行说明如下:
* 第 1 行,执行 go env 指令,将输出当前 Go 开发包的环境变量状态。
* 第 2 行,GOARCH 表示目标处理器架构。
* 第 3 行,GOBIN 表示编译器和链接器的安装位置。
* 第 7 行,GOOS 表示目标操作系统。
* 第 8 行,GOPATH 表示当前工作目录。
* 第 10 行,GOROOT 表示 Go 开发包的安装目录。
如果你想修改Go的环境变量,window最好是在系统的环境变量进行添加修改。拿G0PROXY举例。我们要修改成国内的仓库地址。
或者控制台输入go env -w GOPROXY=https://goproxy.cn,注意加上-w,我就是没加上导致改了没反应。
二.Go path
在go1.12以前,go所有的包文件都放在gopath路径下,导致项目的管理很烦人。现在已经Go 1.19了,有了go mod管理工具的出现,可以不用在gopath上管理,可以在你任意的路径上开发go。但是呢,gopath作用被削弱了,但是他仍要搞清楚,它现在的作用。毕竟它曾劝退很多新手,包括我。
目录
$HOME/go
--bin # 存放编译后的可执行文件
--pkg # 依赖包编译后的*.a文件
--src # 存放源码文件,以代码包为组织形式
1.1 bin目录
存放编译后的可执行文件。注意,go install进行编译默认放在此目录。go build就没有在此目录,在项目的相对路径。
1.2 pkg目录
存放包文件。当用户从外面导入包后,默认存放于此。另外,用go install进行编译时,也可能有包文件(.a)存放于此。
这里对.a文件有了疑问,便百度了一下。
.a文件是静态库,多个静态链接库可以组成二进制可执行文件。 我们通常需要把一些公用函数制作成函数库,供其它程序使用,函数库分为静态库和动态库两种。 静态库在程序编译时会被连接到目标代码中,程序运行时不在需要该静态库。 动态库在程序编译时并不会被连接到目标代码中,而是在程序运行时才被载入。这样我们可以通过更改动态库,动态的改变程序的某些功能。 Linux下使用ar工具,将目标文件压缩到一起,并且对其进行编号和索引,以便于查找和检索。
看到这里,好像知道了go intall和go bulid区别。
1.3 src目录
用于存放源码文件。go mod出现以来,gopath的目录默认没有src目录,但是网上流行使用在gopath的目录上建src目录进行项目管理。这个看个人喜好,无可厚非。但是建议采用流行的做法,项目开发时能减少包依赖的麻烦。
1.4 Go path例子:
bin/
streak # 可执行命令
todo # 可执行命令
pkg/
linux_amd64/
code.google.com/p/goauth2/
oauth.a # 包对象
github.com/nf/todo/
task.a # 包对象
src/
code.google.com/p/goauth2/
.hg/ # mercurial 代码库元数据
oauth/
oauth.go # 包源码
oauth_test.go # 测试源码
github.com/nf/
streak/
.git/ # git 代码库元数据
oauth.go # 命令源码
streak.go # 命令源码
todo/
.git/ # git 代码库元数据
task/
task.go # 包源码
todo.go # 命令源码
此工作空间包含三个代码库(goauth2、streak 和 todo),两个命令(streak 和 todo) 以及两个库(oauth 和 task)。
三.Go module
前提开启gomod。go env开启,go env GO111MODULE=on
快速上手
- 先在projiect路径下输入go mod init,这是生成一个go.mod文件,里面会记录相关依赖信息。
go.mod 的内容 第一行:模块的引用路径 第二行:项目使用的 go 版本 第三行:项目所需的直接依赖包及其版本
- 接着就可以再这个路径下开发了。
- 你可以先导包进来
go get xxx或者go mod download xxx,两者有所区别,新手使用go get最好。 - 或者可以先写完,再进行导包。
使用
go mod tidy进行依赖检查,它会自动导入,并写在go.mod上。 - 又或者不进行导包,编译时会帮你导包。这种偷懒方法不建议。但你存在多个版本的包时,会出错。 想要深入了解Go module可以看看这篇大佬的文章。
四.辨析
4.1 go install与go build
这个问题是在编译go文件产生的疑问,为啥我的.exe在项目里而不在bin里,由此找到这。
a. 作用
- go bulid:用于测试编译包,在项目目录下生成可执行文件(有main包),无main包将报错。
- go install:主要用来生成库和工具。无main包情况下,编译包文件(.a),将编译后的包文件放到
$GOPATH/pkg目录下。有main包情况下,编译生成可执行文件,将可执行文件放到$GOPATH/bin目录。 可见go install更加全面。但是go install在更多是用来编译第三方包。为啥,文件那么多,用go install包容性强,不便于测试。有些包修改完,在本地使用就得用go instsll。
b.参数表
只能说是亲兄弟,一摸一样。
| 参数名 | 格式 | 含义 |
|---|---|---|
| -o | -o file | 指定编译后二进制文件名 |
| -a | -a | 强制重新编译涉及的依赖 |
| -s | -s | 省略符号表并调试信息 |
| -w | -w | 省略 DWARF 符号表 |
| -p | -p | 指定编译过程中的并发数,默认为CPU数 |
| -work | -work | 设置该参数后不会在程序结束后删掉编译的临时文件,可用于参看编译生成的文件 |
| -n | -n | 加上该参数可以查看编译的过程,但不会继续执行编译后的二进制文件 |
| -x | -x | 加上该参数可以查看编译的过程,会继续执行编译后的二进制文件 |
c.省流
项目编译用go bulid,远程包用go install。
4.2 go install与go get
版本历史遗留问题,这里不管历史,直接给结论。
- go get: 对 go mod 项目,添加,更新,删除 go.mod 文件的依赖项(仅源码)。不执行编译。侧重应用依赖项管理。
- go install: 在操作系统中安装 Go 生态的第三方命令行应用。不更改项目 go.mod 文件。侧重可执行文件的编译和安装。
__ 软件更迭快,不断学习才能进步的😢。__go install要去深究还能扯出更多。所以,代码能跑就行。🤣
参考资料
- go-zh.org/doc/code.ht…
- c.biancheng.net/view/88.htm…
- blog.csdn.net/m0_51504545…
- blog.csdn.net/WHQ78164/ar…
有问题请指出,我将感激不尽!