package a
import (
"fmt"
"cc/c"
)
func Out() {
fmt.Println(c.GetB())
}
func GetA() string {
return "a"
}
func init() {
c.GetA = GetA
}
package b
import (
"fmt"
"cc/c"
)
func Out() {
fmt.Println(c.GetA())
}
func GetB() string{
return "b"
}
func init() {
c.GetB = GetB
}
package c
var GetA func()string
var GetB func()string
就是 a 和 b 在 init 的时候, 向 c 注册, c 不引任何包, 这样的做有什么问题吗?
1
sadfQED2 2022-07-30 10:16:31 +08:00 via Android
你这个难道能编译通过? GetA 不是一个函数吗,你怎么能给函数赋值?
|
2
jinliming2 2022-07-30 11:08:27 +08:00 via iPhone
@sadfQED2 GetA 看着是个函数指针啊?😯
|
3
janxin 2022-07-30 14:02:44 +08:00 via iPhone
可以是可以,但是你未来很难保证你的这个包只有函数和基本类型吧
|
4
fujianjian OP @janxin 是的, 但是包里有几个方法很难再拆包了, 社交的业务代码比较杂乱, 暂时采取这种丑陋的方式
|
5
katsusan 2022-07-30 18:22:37 +08:00
|
6
mauve 2022-07-31 20:03:31 +08:00
也许不用写这么复杂,这不就是个全局变量吗?
用全局变量解决 import cycle 好吗?不好 |
7
fujianjian OP @katsusan 我上面写的办法应该跟 cockroachdb 的 Dependency injection 的方案是类似的 :)
|
8
fujianjian OP @mauve 所以也一直觉得比较丑陋, 但是更好的办法也还没找到
|
9
mauve 2022-08-01 01:00:10 +08:00
我想到的三种做法,越往后的越好
1. 包下拆分子包,a 引入 a 下的子包 c ,b 作为与 a 同级别包也引入 a 包下的子包 c ; c 内尽量保持简洁不额外依赖,很多 model 包会这么做 2. 使用 wire 或者类似依赖注入的方案 ,https://github.com/google/wire ,wire 将所有依赖按照 hierarchy 汇总成一个 Application ,向面向对象一样,方法调用时尽量调用 Method 而不是 Function 3. 在 2. 的基础上拆分业务逻辑,面向接口编程,向 5 楼发的一样,将一些类似的业务逻辑提取成 Interface ,a 包 b 包皆依赖于 c 包中的 Interface ,而不必关心相互是否实现 另外,还是尽量避免使用 init 吧 |