我们可以输入go env
查看我们的go环境变量
GOPATH="/Users/inf/go"
GOROOT="/usr/local/go"
GO111MODULE="auto"
GOPATH
GOPATH 是 Go语言中使用的一个环境变量,它使用绝对路径提供项目的工作目录。
- 工作目录:一个工程开发的相对参考目录。工作区的概念与工作目录的概念也是类似的。如果不使用工作目录的概念,在多人开发时,每个人有一套自己的目录结构,读取配置文件的位置不统一,输出的二进制运行文件也不统一,这样会导致开发的标准不统一,影响开发效率。
命令行输出我们可以看到go的工作目录GOPATH默认为/Users/xxx/go/
使用GOPATH的工程结构
在 GOPATH 指定的工作目录下,代码总是会保存在 $GOPATH/src
目录下。在工程经过 go build
、go install
或 go get
等指令后,会将产生的二进制可执行文件放在 $GOPATH/bin
目录下,生成的中间缓存文件会被保存在 $GOPATH/pkg
下。
如果需要将整个源码添加到版本管理工具(Version Control System,VCS)中时,只需要添加 $GOPATH/src
目录的源码即可。bin 和 pkg 目录的内容都可以由 src 目录生成。
设置和使用GOPATH
我们可以使用命令
export GOPATH=`pwd`
选择一个目录,在目录中的命令行中执行下面的指令:设置当前目录为GOPATH
该指令中的 pwd
将输出当前的目录,使用反引号`将 pwd
指令括起来表示命令行替换,也就是说,使用 `pwd` 将获得 pwd 返回的当前目录的值。例如,假设你的当前目录是“/Users/xxx/go”,那么使用pwd
将获得返回值“/Users/xxx/go”。
使用 export 指令可以将当前目录的值设置到环境变量 GOPATH中。
网上建议大家无论是使用命令行或者使用集成开发环境编译 Go 源码时,GOPATH 跟随项目设定。在 Jetbrains 公司的 GoLand 集成开发环境(IDE)中的 GOPATH 设置分为全局 GOPATH 和项目 GOPATH,如下图所示
Global GOPATH 代表全局 GOPATH,一般来源于系统环境变量中的 GOPATH;Project GOPATH 代表项目所使用的 GOPATH,该设置会被保存在工作目录的 .idea 目录下,不会被设置到环境变量的 GOPATH 中,但会在编译时使用到这个目录。建议在开发时只填写项目 GOPATH,每一个项目尽量只设置一个 GOPATH,不使用多个 GOPATH 和全局的 GOPATH。
GOROOT
GOROOT就是我们Go语言的安装路径。我这里是/usr/local/go
打开这个文件夹,同样可以看到
src, bin, pkg三个文件夹,
标准的Go语言代码库中包含了大量的包,并且在安装 Go 的时候多数会自动安装到系统中。我们可以在 $GOROOT/src/pkg 目录中查看这些包。当我们 import内置包的时候,并不需要额外安装,当程序运行时,会先去GOROOT下找相应的包来运行。
我们可以在其他随便一个文件夹下运行GOPATH/src下运行mian.go
比如我新建了一个hello文件夹,
//main.go
package main
import "fmt"
func main() {
fmt.Println("Hello World")
}
会成功输出Helo World,go run其实帮你将程序进行编译并生成可执行文件,而编译文件和执行文件实际上存在在一个暂存资料夹里面,当运行完这个程序就会自动删除。该指令可以相乘类似直译的方式运行,而不需要其他任何环境设定。
但如果
要引入hello.go,或者import 某个Github上的包,就会报错
import (
"hello"
)
func main() {
test1()
}
// main.go:10:3: cannot find package "hello" in any of:
// /usr/local/go/src/hello (from $GOROOT)
// /Users/inf/go/src/hello (from $GOPATH)
1、 当执行golang程序,需要获取import的包时,编译器回先去GOROOT路径下的src文件夹找有没有我们在程序中import的包
2、如果在GOROOT下没有找到,就会去GOPATH下src下找这个包
所以只要GOROOT跟GOPATH下都没找到包的话就会报错
go run, go build, go install
go run
go run 编译并直接运行程序,它会产生一个临时文件(但不会生成 .exe 文件),直接在命令行输出程序执行结果,方便用户调试,产生执行结果后就会自动删除。
go build
go build 用于测试编译包,主要检查是否会有编译错误,如果是一个可执行文件的源码(即是 main 包),就会直接生成一个可执行文件。
go build main.go
这样会在当前目录下产生一个名称为mian的可执行文件。也可以在build后面写专门的项目名称,执行该命令会自动在当前文件夹下找package为mian,并且有main function的go文件,再编译成可执行文件
也可以使用下面的命令指定build出来的可执行文件放在哪里
go build -o bin/main src/demo/main.go
-o后面的第一个参数表示生产的可执行文件的路径以及名称,第二个参数代表要编译的go文件的路径。
按照惯例,GOPATH下bin文件夹存放build出来的可执行文件。
go build有个缺点就是每次编译go文件比较没有效率,当项目架构越来越大build的速度也越来越慢。
go install
go install 的作用有两步:第一步是编译导入的包文件,所有导入的包文件编译完才会编译主程序;第二步是将编译后生成的可执行文件放到 bin 目录下($GOPATH/bin
),编译后的包文件放到 pkg 目录下($GOPATH/pkg
)。
go install 做两件事情,
- 将package编译成.a file
- 如果是main 包则编译成可执行文件
有了第一项功能,下次编译时候就不会将包的程序码重新编译,而是直接用编译好的.a file。而.a file就位于GOPATH/pkg里面。
来看一个例子
GOPATH/src下新建两个项目mypkg和mytest,分别新建两个go文件
mypkg.go
package mypkg
import "fmt"
func MyFunc() {
fmt.Println("MyFunc")
}
mytest.go
package main
import (
"mypkg"
)
func main() {
mypkg.MyFunc()
}
mytest.go中用了import了mypkg的包,而可以通过install指令将mypkg编译成.a file
go install mypkg
可以发现在GOPATH/darwin_amd64/mypkg.a
有该文件
darwin_amd64是由GOOS和GOARCH两个环境变量所组合合成的
GOPATH缺点
当我们的第三方包不是官方库时都要放在GOPATH/src下才可以使用
我们通常使用go get指令来获取第三方的包
go get github.com/gin-gonic/gin
go get 最长用在当我们想用别人公开在github上的包,可以帮我们从网上clone到GOPATH/src下。
是不是听起来很方便?会让src下的项目变得很复杂,除了有自己的项目还有其他第三方库的项目。
在如果,我们的不同的项目采用的第三方库是不同的版本怎么办,go1.11以前是要设顶多组不同的GOPATH,虽然go社区也有开发相对应的包管理工具,如Vender,Dep来结局该问题,但它们都不是官方的。
GOMOD
Go Modules很像java的maven,将第三方的库放在本地的空间,但它不是自动的下载包的
如下命令开启和关闭go mod
go env -w GO111MODULE=on 打开
go env -w GO111MODULE=off 关闭
GO111MODULE有三个不同的值
-
auto
- 当存在 go.mod 文件时或处于 GOPATH 外, 其行为均会等同于于 GO111MODULE=on。这意味着在 Go 1.13 及之后的版本你可以将所有的代码仓库均存储在 GOPATH 下。
- 当处于 GOPATH 内且没有 go.mod 文件存在时其行为会等同于 GO111MODULE=off。
on
即使项目在您的 GOPATH 中,GO111MODULE = on 仍将强制使用 Go 模块。需要 go.mod 正常工作off
强制 Go 表现出 GOPATH 方式,即使在 GOPATH 之外。
下载下来的第三方库在哪呢?其实就在GOPATH/pkg/mod文件夹里面
接下来就是和maven很像的操作了
src下新建一个文件夹modtest
该文件夹下执行
go mod init <module name>
<module name>可填可不填,不填的话就是采用项目文件夹的名称,执行后会出现一个go.mod的文件
module modtest
go 1.15
go.mod 提供了module, require、replace和exclude 四个命令
module 语句指定包的名字(路径)
require 语句指定的依赖项模块,默认最新版,可以指定版本号
replace 语句可以替换依赖项模块
exclude 语句可以忽略依赖项模块
还有个go 命令定义go语言的版本
添加一个,假设我要引入github.com/gin-gonic/gin v1.5.0这个包
module modtest
go 1.15
require github.com/gin-gonic/gin v1.5.0
在执行
go mod download
会发现当前文件夹下多了个go.sum的文件,该文件基本上用来记录包版本的关系,不怎么需要理会。需要的包装在GOPATH/pkg/mod文件夹下
之后运行
go run main.go
GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080
这个就是在local 8080 port开启一个web server~
当然也可以不执行go mod download而直接运行go build或者go install也会自动下载包
还有一种方法可以直接下载
使用go get命令
go get github.com/gin-gonic/gin@v1.6.3
或者require指定版本,执行go get指令。和download是一样的。
只要有开启gomod功能,go get就不会再src下放package,而是会放在/pkg/mod里面,并且mod会写好引入。也就不需要go mod download了
有疑问加站长微信联系(非本文作者)