一个会导致 go build panic 的 bug


起因是因为犯懒,随手在一个函数体内定义一个类型

func foo() {
	type Article = map[string]interface{}
}

看起来好像也很正常,突然有一天在 gowatch 的控制台里看到了

runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow
runtime stack:
runtime.throw(0x1a556a1, 0xe)
/usr/local/Cellar/go/1.12.5/libexec/src/runtime/panic.go:617 +0x72
runtime.newstack()
/usr/local/Cellar/go/1.12.5/libexec/src/runtime/stack.go:1041 +0x6f0
runtime.morestack()
/usr/local/Cellar/go/1.12.5/libexec/src/runtime/asm_amd64.s:429 +0x8f
...

以为是程序出 panic 了,不过仔细看了看,好像不是我的代码,仔细一研究,发现程序还没跑起来,go build 时已经 panic 了。然后经过各种 git stash,终于发现,原来是因为外面也定义了一个 type Article struct{} 导致的 panic。

印象中函数体内和函数外是可以重名的,而且,即便不可以,也应该编译失败才对,怎么就 panic 了。

于是尝试了一下

如果同时定义两个重名类型,会提示 redeclared in this block

type A struct{}
type A = map[string]string

// A redeclared in this block

如果分开到两个 block,就编译通过了。

type A struct{}
func main(){
	type A = map[string]string
}

// build success

奇了个怪。那为什么我的程序会 panic 呢?

又经过尝试,终于发现,在本包内正常调用是可以的,只有当其他包引用此包时才会 panic。而且,如果把函数体内的 type X = Y 改成 type X Y 也是可以编译通过的。

总结起来,两个条件:

  • 在两个 block 内同时定义 type Xtype X=
  • 在其他包里引入此包

之后,给 goteam 提了个 issue 来反馈这个诡异的 bug

忧伤的地方来了,自己只能发现 bug,完全不具备追查 bug 产生的原因。

立个 flag 吧,希望有时间可以研究研究编译器相关的一些知识。

Avatar
huiren
Code Artisan

问渠那得清如许,为有源头活水来

相关

下一页
上一页
comments powered by Disqus