老弟有空吗,我Go项目里某个init函数被调用了两次!

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

内容简介:周五快要下班了,同事过来找我,说他的Go项目里某个init函数被调用了两次。WTF,这不耽误回家过周末吗!废话不多说,直接上同事工位看现场。同事向我展示了两行内容相同的日志,并且与之对应的源码。大概像下面这样:

周五快要下班了,同事过来找我,说他的 Go 项目里某个init函数被调用了两次。WTF,这不耽误回家过周末吗!

废话不多说,直接上同事工位看现场。

同事向我展示了两行内容相同的日志,并且与之对应的源码。大概像下面这样:

func init() {
    log.Info("xxx")
}

我让同事将代码中的日志稍微做了些修改。大概像下面这样:

func init() {
    //log.Info("xxx")
    log.Info("yyy")
}

重新运行,打印出的日志变成了两行 yyy ,说明日志确实是由该处产生的。

我怀疑是init函数被手动调用了。由于init函数是小写开头的,包外应该调用不了,所以我让同事在包内搜索是否有手动调用的地方,结果没有。

(事后实验证明,Go不允许手动调用init函数,会产生编译错误)。

于是我又想了想,Go中的init函数会否由于多次import造成多次调用。应该是不会,不然日常很多代码都应该有问题。

由于同事编写代码的环境,编译环境,运行环境可能不在一台机器上,我怀疑是中途某个环节同步代码时出错了。

所以我将代码再次做了些修改。大概像下面这样:

// 声明一个包(全局)作用域的变量
var tmp int

func init() {
    //log.Info("yyy")

    // 此处,我没再用代码中引入的第三方log库,而是使用标准库中的log库,目的是将源码文件打印出来
    log.SetFlags(log.Llongfile)
    // 看两次打印的tmp值,以及对应的地址
    log.Printf("zzz %d %p", tmp, &tmp)
    tmp = 10
}

打印出的结果显示,两次tmp的值都是0,并且地址是不同的。

更为关键的是,打印出的源码文件是不同的!大概像下面这样:

github.com/test/x/config.gogithub.com/test2/x/config.go

到此问题基本定位到了,反馈给同事,同事说项目的git路径确实发生过变化,由 test 变成了 test2 ,于是他做了个软链。。

那么原因也找到了,应该是代码中同时import了 testtest2 导致的。

至于具体是哪个地方import的,我就不关心了。

向同事说明,Go中以package为单位管理代码,两个不同路径的package,即使代码完全相同,依然是两个package。

当有依赖全局状态时,可能就会出现问题。比如同事的业务代码就不允许init被调用两次,根本原因,也基本能猜到是有全局状态。

或者换个角度理解,我添加的代码中,出现了两个tmp可能就会隐藏某些bug。

闪人,回家过周末。

回家的路上,我又想了想,定位这个问题是否有更快的手段。

可以在init函数中把调用堆栈打印出来,但是init函数的调用应该是编译器生成的,在main入口处调用,由于我确认了init函数无法手动调用,所以打堆栈基本也没什么卵用。

使用go list将项目依赖的所有包打印出来,这个方法应该也行得通。

但是前文也说了,由于他们的项目,开发、编译、运行可能不是一个机器,甚至编译时的go命令都是经过封装过的工具,我也绕不清。也就不好去go list。理论上环境单纯的话,在编译机go list也是可以的。

不过这也有点事后诸葛亮,事实上,我最后定位到问题时用的方法,我事先也没有明确猜到是import两处相同代码引起的,我只是隐约怀疑代码在编译过程中发生了拷贝。

原文链接: https://pengrl.com/p/20030/

原文出处: yoko blog ( https://pengrl.com )

原文作者: yoko ( https://github.com/q191201771 )

版权声明:本文欢迎任何形式转载,转载时完整保留本声明信息(包含原文链接、原文出处、原文作者、版权声明)即可。本文后续所有修改都会第一时间在原始地址更新。

老弟有空吗,我Go项目里某个init函数被调用了两次!


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

查看所有标签

猜你喜欢:

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

看见未来

看见未来

余晨 / 浙江大学出版社 / 2015-4-15 / 59.00元

【内容简介】 这是互联网群星闪耀的时代,巨人们用最尖端的技术和自成体系的哲学改变着我们的生活,甚至影响了整个世界和人类的历史进程。在这个时代,没有人可以避开互联网的渗透。互联网早已不是简单的技术变革,人们正试图赋予其精神和内涵,以期互联网能更好地为人类所用。 本书中作者 面对面地采访了包括马克·扎克伯格、埃隆·马斯克、杨致远、凯文·凯利、克里斯·安德森、罗伯特·希勒、迈克尔·莫瑞茨、凯......一起来看看 《看见未来》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

html转js在线工具
html转js在线工具

html转js在线工具