老弟有空吗,我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函数被调用了两次!


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

查看所有标签

猜你喜欢:

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

CSS与DHTML精髓(第2版)

CSS与DHTML精髓(第2版)

Dan Livingston / 清华大学 / 2003-7-1 / 34.00

CSS与DHTML精髓(第二版),ISBN:9787302066941,作者:战晓苏译;战晓苏译一起来看看 《CSS与DHTML精髓(第2版)》 这本书的介绍吧!

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

在线压缩/解压 HTML 代码

SHA 加密
SHA 加密

SHA 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具