为何未调用checkLink的两个Go程序行为有差异?编译程序被删原因?
问题原因拆解
1. 两个程序行为差别的核心:init函数在搞事情
你说没调用checkLink,但Go程序会自动执行所有包级的init函数,俩程序的差异肯定出在这:
- Program 1:
init里启动的goroutine大概率在操作未正确初始化的通道或同步锁,导致所有goroutine(包括main)都堵死了。Go运行时能检测到这种“所有goroutine都休眠”的情况,直接抛出all goroutines are asleep - deadlock!然后终止程序。 - Program 2:
init里的goroutine可能是在等一个永远不会来的信号(比如空通道的接收操作),但main goroutine没退出(比如main函数是空的,或者也在无限等待)。Go的死锁检测只在所有goroutine都阻塞时触发,要是main还在跑(哪怕是空循环),就不会报错,程序就一直挂着。
2. go build生成的可执行文件被删的原因(macOS+ZSH)
这和Go本身没关系,大概率是两种情况:
- 你Program 2的代码里写了主动删除自身的逻辑(比如用
os.Remove删除当前可执行文件的路径)。 - ZSH的配置或者安全软件(比如Mac的隐私保护、第三方杀毒工具)把这个无输出的挂起进程当成异常,直接终止进程还删除了可执行文件。可以换bash环境试试,或者暂时关闭安全软件验证。
3. Go Tour里Program 2和Program 1行为一致的原因
Go Tour是沙箱化运行环境,会给程序设置超时时间,而且死锁检测逻辑和本地go run对齐。当Program 2的goroutine堵死之后,沙箱要么触发超时,要么检测到死锁,直接终止程序,所以表现和Program 1一致。
验证小技巧
- 检查两个程序的
init函数和包级变量初始化代码,找启动goroutine、操作通道的差异。 - 给Program 2的可执行文件先备份一份,运行后看备份是否还存在,排除代码主动删除的可能。
- 在Program 2的main函数里加一行
fmt.Println("main done"),看能不能正常输出,判断main goroutine有没有正常退出。
内容的提问来源于stack exchange,提问作者Sandeep Singh
相关产品推荐
相关产品推荐

