go1.17+中的GOPATH

虽然golang已经从1.17废弃了gopath的包管理方式,但目前gopath是对ide最友好的,vendor也可以,但会造成本地磁盘代码膨胀,以现在流行的微服务架构,动辄上百个项目,磁盘受不了。

通过 GO111MODULE="off" 启用gopath。

GOPATH 环境变量可以设置多个目录,比如共享的gopath和本项目自身的根目录(/myroot/src/mydomain/myproject/*中的myroot),当go get时使用第一个目录存放拉取的包。

当 GOPATH 包含多个目录时,在windows下和linux下目录列表分隔符是不同的,如下:

linux:

const (
	PathSeparator     = '/' // OS-specific path separator
	PathListSeparator = ':' // OS-specific path list separator
)

windows:

const (
	PathSeparator     = '\\' // OS-specific path separator
	PathListSeparator = ';'  // OS-specific path list separator
)

对import中大版本的支持:

GO111MODULE="off" 时,如源码引入了:import "github.com/go-acme/lego/v3/acme",

通过 go get github.com/go-acme/lego/v3/acme 只能下载最新版本的包,并不能自动切到v3下。

只能通过两种方式解决:

1、到lego目录下手动切到v3下,如:git checkout v3.9.0

缺点:没办法处理版本冲突,如果存在一个代码库多个 /vN 的大版本依赖,只能通过下面的方式解决:

2、将lego目录更名为v3,并在v3前面新增lego目录,然后到v3目录下手动切到v3.9.0的tag下。
 

是否启用 GO111MODULE 对go get命令的版本格式也有影响,甚至诡异,以go1.18为例:

一、当 GO111MODULE = off 时,下载存放目录是gopath/src/,版本表示如下:

当使用 go get example.com/pkg 时,下载的是最新版。

当使用 go get example.com/pkg/v2.1.0 时,下载的仍然是最新版,指定的tag无效。

当使用 go get example.com/pkg@v2.1.0 时,报语法错误。

二、当 GO111MODULE = on 时,下载存放目录是gopath/pkg/mod/,版本表示如下:

2.1 当要下载的目标包在 go.mod 文件中未指定大版本时:

当使用 go get example.com/pkg 时,下载的是最新版。

当使用 go get example.com/pkg/v2 时,大版本不生效,下载的是最新tag。

当使用 go get example.com/pkg/v2@v2.1.0 时,大版本不生效,下载的是指定tag v2.1.0。

当使用 go get example.com/pkg@v2.1.0 时,下载很顺滑,下载的是指定tag v2.1.0。

2.2 当要下载的目标包在 go.mod 文件中通过 module example.com/pkg/v2 指定大版本时:

当使用 go get example.com/pkg 时,下载的也许是本地也许是远程代理的缓存版本,未必是最新版。

当使用 go get example.com/pkg/v2 时,下载的是v2大版本下的最新tag。

当使用 go get example.com/pkg/v2@v2.1.0 时,下载的是v2大版本下的指定tag v2.1.0。

当使用 go get example.com/pkg@v2.1.0 时,报错invalid version,也就是tag需要放到大版本下。

观察 GOPROXY 的代理是否生效:

go get -x example.com/pkg

将gopath目录中的依赖移到项目vendor目录下:

可以通过govendor工具解决,github.com/kardianos/govendor 已经停止更新,但是还可以使用。

一、安装govendor:

go install github.com/kardianos/govendor

二、初始化vendor目录:

GO111MODULE="off" GOPATH=/my_gopath:/project_root govendor init

三、将gopath依赖移到vendor:

GO111MODULE="off" GOPATH=/my_gopath:/project_root govendor add +e

此命令会全量扫描项目代码和项目依赖的代码,找出所有依赖,然后复制到vendor目录下,很耗时。

缺点:govendor 不能识别go.mod中的大版本标识,所以对于类似 github.com/go-acme/lego/v3/acme 的依赖会提示找不到,只有依赖包名和gopath路径完全一致时才能工作。

四、基于vendor目录编译项目:

GO111MODULE="off" GOPATH=/project_root go build main.go

在vscode中启用老式的gopath支持:

1、修改项目的环境变量:

打开workspace里的go插件配置,如下图,然后点击edit in settings.json

在settings.json里添加环境变量如下:

{
    "go.toolsEnvVars": {
        "GO111MODULE" : "off"
    },
    "go.inferGopath": true
}

 2、打开go插件的根据项目root推断gopath设置:

 vscode会自动在settings.json里添加一行:"go.inferGopath": true

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值