一个比较无耻的解决方案
开始
这里讲的方法千万不要使用,为什么写这一篇文章是因为在工作中就很少想到有这样的奇淫巧技了。
案例
我有一个a包,里面封装了用户的一些基本信息
// User basic user info
type User struct {
Username string
Password string
IdCard string
}
// UpdateUserInfo 更新用户信息
func UpdateUserInfo(idCard string) {
b.UpdateUserInfo(getAgeFromIdCard(idCard))
}
func getAgeFromIdCard(idCard string) (age int) {
// do something
return
}
当用户更新信息的时候会调用 UpdateUserInfo
方法,但是用户的一些其余信息定义在了B包中。这里就产生了循环引用问题。
// User extend a.User
type User struct {
a.User
Age int `json:"age"`
}
// UpdateUserInfo 刷新用户信息
func UpdateUserInfo(age int) {
// do something
}
解决方案
我们可以保证A包是基本包,它始终不调用任意其余包,这样我们可以通过初始化的方式把B包中的方法传递给A包,这样就解决了循环引用问题,大概就是在A包中增加一个接口(广义的接口)使得A包可以通过调用本地方法的方式来调用B包中的函数。
// a包
var (
BUpdateUserInfoFunc func(age int)
)
// b包
func Init() {
a.BUpdateUserInfoFunc = UpdateUserInfo
}
当然也可以通过其余方式(比如消息队列或者其余的同步方法)
写在最后
水了一周的文章,这样做的意义不大,甚至危害性极高,它使得基础包A包增加了过多的初始化依赖,并且有可能出现循环调用的问题,这无异于一场灾难。