本文转载自微信公众号《我的脑子是炸鱼》,作者陈建宇。转载本文请联系脑筋急转弯公众号。大家好,我是炸鱼。学习Go语言的开发者越来越多,很多小伙伴在使用的时候也会遇到各种看不懂的问题。其中一个是包循环引用的错误:packagecommand-line-argumentsimportsgithub.com/eddycjy/awesome-project/aimportsgithub.com/eddycjy/awesome-project/bimportsgithub.com/eddycjy/awesome-project/a:importcyclenotallowedatonce很疑惑,为什么Go不支持包之间的循环引用?案例演示这里我们将做一个基础的案例演示,让没有接触过的同学可以建立一个初步的了解。我们的程序分别有2个包。a包代码如下:import("github.com/eddycjy/awesome-project/b")funcHello(sstring){b.Print(s)}b包代码如下:import("fmt""github.com/eddycjy/awesome-project/a")funcHello(){a.Hello("Thebrainisfryingfish")}funcPrint(sstring){fmt.Println(s)}并调用a.Helloinmain.go文件(“大脑是炸鱼”)方法。运行后会出现如下错误信息:importcyclenotallowederror原因是a包引用b包,b包引用a包,导致循环引用。这在Go语言中是明令禁止的,程序在编译过程中会被打断,导致编译失败。原因分析按照目前Go官方的统一意见,循环导入包几乎是不可能的,甚至Go2也被明确拒绝了。因为Go2可能是破解很多核心问题的关键节点,所以很多人提出了《proposal: Go 2: allow import cycle》这样的提案,希望能够解决循环引入的问题。Go语言之父RobPike亲自回答了这个问题,理由如下:不支持循环引用:目的是迫使Go程序员更多地考虑程序依赖性。保持你的依赖图干净。快速的程序构建。如果支持循环引用:很容易造成懒惰、依赖管理不佳和构建缓慢。这是设计者不愿看到的。凌乱的依赖。程序构建缓慢因此,首先要考虑保持依赖图的正确DAG,RobPike认为这是一个值得预先简化的领域。在Go程序中执行导入循环可能很方便,但它们背后的成本可能是灾难性的,并对Go构建性能和依赖项产生非常不利的影响。所以在Go中明确禁止支持。综上所述,在程序中,如果我们经常出现模块之间的循环引用,这个时候我们是否应该思考一下,是不是设计出了一些问题,是否应该考虑调整?但并不是所有的东西都是二极管,Go源码可能或多或少都有自己的循环引用案例,最重要的是想清楚。
