小心go.mod中的go directive

栏目: IT技术 · 发布时间: 4年前

内容简介:在撰写《在我进行overlapping interface试验时,我使用go 1.14编译器编译下面的代码:但出乎意料的是我得到了如下的结果:

在撰写《 Go 1.14中值得关注的几个变化 》这篇文章时,我使用的试验环境为我的2019款 MacPro,OS版本:10.14.6。我通过下载 https://dl.google.com/go/go1.14.darwin-amd64.tar.gz 并解压的方式安装的 Go 1.14版本。在我的工作环境中,我通常通过变更 GOROOT 的方式来使用不同的Go版本。但在进行Go 1.14新增的overlapping interface的实验时,我遇到了一个问题。本文记录的就是这个问题的发现和解决过程,以备自己备忘,也希望能给广大Gopher带来启发。

1. 问题现象

在我进行overlapping interface试验时,我使用go 1.14编译器编译下面的代码:

// https://github.com/bigwhite/experiments/blob/master/go1.14-examples/overlapping_interface.go

package foo

type I interface {
    f()
    String() string
}
type J interface {
    g()
    String() string
}

type IJ interface {
    I
    J
}

但出乎意料的是我得到了如下的结果:

$go build overlapping_interface.go
# command-line-arguments
./overlapping_interface.go:14:2: duplicate method String

我一脸懵逼啊!我靠! Go 1.14 的新增的 overlapping interface机制 居然不好用!之后我的第一反应就是检查是不是我的当前窗口中GOROOT设置有误,结果:GOROOT设置完全没错!

于是我又切换到一个Ubuntu 18.04环境下,同样用Go 1.14版本(for linux)编译上述代码,这回编译很顺利,没有报出像MacOS那样的错误。

接下来进入胡思乱想状态:) 难道是Go team在打包go1.14.darwin-amd64.tar.gz是忘记了这个功能?…. …..

2. 问题分析过程

我首先到 go项目的issue列表 查是否有人遇到与我相同的问题,居然没找到,基本肯定是我自己环境的问题了。于是提了 一个issue ,看看有谁能帮忙分析一下原因。

不久,Go核心开发团队的 Keith Randall 提供了一些信息和诊断思路。首先他在他自己的Mac环境无法重现该问题,并也怀疑是不是我的安装方式和环境变量设置的问题。

于是,我尝试了更换一种Go 1.14的安装方式来重新安装Go 1.14 for MacOS:

$go get golang.org/dl/go1.14
go: finding golang.org/dl latest
go: downloading golang.org/dl v0.0.0-20200302224518-306f3096cb2f
go: extracting golang.org/dl v0.0.0-20200302224518-306f3096cb2f

$go1.14 download
Downloaded   0.0% (    14448 / 124931758 bytes) ...
Downloaded   0.3% (   391280 / 124931758 bytes) ...
... ...
Downloaded  92.5% (115554516 / 124931758 bytes) ...
Downloaded 100.0% (124931758 / 124931758 bytes)
Unpacking /Users/tonybai/sdk/go1.14/go1.14.darwin-amd64.tar.gz ...
Success. You may now run 'go1.14'

$go1.14 env
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/tonybai/Library/Caches/go-build"
GOENV="/Users/tonybai/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/tonybai/Go"
GOPRIVATE=""
GOPROXY="https://goproxy.cn,direct"
GOROOT="/Users/tonybai/sdk/go1.14"
GOSUMDB="off"
GOTMPDIR=""
GOTOOLDIR="/Users/tonybai/sdk/go1.14/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"

PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/cz/sbj5kg2d3m3c6j650z0qfm800000gn/T/go-build236598550=/tmp/go-build -gno-record-gcc-switches -fno-common"

我使用renew后的go1.14再来编译最初那段包含了overlapping interface的代码:

➜  /Users/tonybai/Go/src/github.com/bigwhite/experiments/go1.14-examples git:(master) $go1.14 version
go version go1.14 darwin/amd64
➜  /Users/tonybai/Go/src/github.com/bigwhite/experiments/go1.14-examples git:(master) $go1.14 build overlapping_interface.go
# command-line-arguments
./overlapping_interface.go:14:2: duplicate method String

问题依旧!

为了给Keith Randall提供更多有用信息,我在build时传入 -x -v 参数:

➜  /Users/tonybai/Go/src/github.com/bigwhite/experiments/go1.14-examples git:(master) $go1.14 build -x -v overlapping_interface.go
WORK=/var/folders/cz/sbj5kg2d3m3c6j650z0qfm800000gn/T/go-build369480074
command-line-arguments
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg << 'EOF' # internal
# import config
EOF
cd /Users/tonybai/Go/src/github.com/bigwhite/experiments/go1.14-examples
/Users/tonybai/sdk/go1.14/pkg/tool/darwin_amd64/compile -o $WORK/b001/_pkg_.a -trimpath "$WORK/b001=>" -p command-line-arguments -lang=go1.12 -complete -buildid 00YuEePKlhV_qKTnJcVK/00YuEePKlhV_qKTnJcVK -goversion go1.14 -D _/Users/tonybai/Go/src/github.com/bigwhite/experiments/go1.14-examples -importcfg $WORK/b001/importcfg -pack -c=4 ./overlapping_interface.go
# command-line-arguments
./overlapping_interface.go:14:2: duplicate method String

一段时间后,眼尖的Keith Randall发现了蛛丝马迹: -lang=go 1.12 。在我提供的上面build日志中, “-lang=1.12″ 被传给了Go 1.14 compiler,于是虽然贵为go 1.14版本编译器,但它也只能按照go 1.12版本的语法规范对我的代码进行检查和编译,这就是“罪魁祸首”,没跑了!

3. 问题解决

但是”-lang=1.12″怎么就凭空出现传给了Go 1.14编译器了呢?我查了所有编译器相关的环境变量,也没看到哪里设置了-lang=1.12。正当我处于迷茫状态时,突然 go.mod 这个文件名浮现在我的脑海中:go.mod中除了module名、一堆require、replace语句之外,还有 go 1.12 引入的 go 指示信息(directive)! 顿悟!!!

上面所有的go build执行都是在我本地的 /Users/tonybai/go/src/github.com/bigwhite/experiments/go1.14-examples 下执行的。而 github.com/bigwhite/experiments 这个repo的顶层go.mod文件内容如下:

module github.com/bigwhite/experiments

go 1.12

Go 1.12的release note 中,我们看到这样一段说明:

The go directive in a go.mod file now indicates the version of the language used by the files within that module.

go.mod文件中的go指示器指示该当前module中文件使用的Go语言版本。

当前,我的go.mod中go指示器指示的版本为go 1.12,那么即便是使用Go 1.14版本编译器编译该module下的文件,使用的也是go 1.12的语法。

解决方法: 升级go.mod中的go指示器版本为go 1.14 。升级后问题迎刃而解。

4. 小结

目前仅仅在使用比go.mod中go指示器版本低的go编译器对module下源文件进行编译,在报错的时候才会给出版本不匹配的提示。但是如果使用比go指示器版本高的编译器编译,即便出错,也没有警告提示。因此,在升级go版本时, 要小心维护go.mod中的go directive,使其与你使用的go compiler版本匹配

我的网课“ Kubernetes实战:高可用集群搭建、配置、运维与应用 ”在慕课网上线了,感谢小伙伴们学习支持!

我爱发短信 :企业级短信平台定制开发专家 https://51smspush.com/

smspush : 可部署在企业内部的定制化短信平台,三网覆盖,不惧大并发接入,可定制扩展; 短信内容你来定,不再受约束, 接口丰富,支持长短信,签名可选。

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个 链接地址 :https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

Gopher Daily(Gopher每日新闻)归档仓库 – https://github.com/bigwhite/gopherdaily

我的联系方式:

微博:https://weibo.com/bigwhite20xx

微信公众号:iamtonybai

博客:tonybai.com

github: https://github.com/bigwhite

微信赞赏:

小心go.mod中的go directive

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

© 2020,bigwhite. 版权所有.


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

硅谷之火

硅谷之火

迈克尔·斯韦因 / 王建华 / 机械工业出版社 / 2001-1-1 / 34.00

我们今天正处于这样一个时代:充满幻想的人们发现他们获得了他们曾经梦寐以求的力量,并且可以利用这个力量来改造我们的世界。 这是个转折的时代,跨国公司迷失了发展方向,而小企业家却举起了计算机革命的大旗,成了开拓未来的先锋。在这个时代里,计算机奇才的脸上露出了胜利的微笑,胸怀 大志者成了富有理想的人,而富有理想的人则成了亿万富翁。这是一场真正的革命,它促使人们变得伟大,变得富有而充满理想,自豪而富......一起来看看 《硅谷之火》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具