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 不引任何包, 这样的做有什么问题吗?
|  |      1sadfQED2      2022-07-30 10:16:31 +08:00 via Android 你这个难道能编译通过? GetA 不是一个函数吗,你怎么能给函数赋值? | 
|      2jinliming2      2022-07-30 11:08:27 +08:00 via iPhone @sadfQED2 GetA 看着是个函数指针啊?😯 | 
|  |      3janxin      2022-07-30 14:02:44 +08:00 via iPhone 可以是可以,但是你未来很难保证你的这个包只有函数和基本类型吧 | 
|      4fujianjian OP @janxin 是的, 但是包里有几个方法很难再拆包了, 社交的业务代码比较杂乱, 暂时采取这种丑陋的方式 | 
|      5katsusan      2022-07-30 18:22:37 +08:00 | 
|  |      6mauve PRO 也许不用写这么复杂,这不就是个全局变量吗? 用全局变量解决 import cycle 好吗?不好 | 
|      7fujianjian OP @katsusan 我上面写的办法应该跟 cockroachdb 的 Dependency injection 的方案是类似的 :) | 
|      8fujianjian OP @mauve 所以也一直觉得比较丑陋, 但是更好的办法也还没找到 | 
|  |      9mauve PRO 我想到的三种做法,越往后的越好 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 吧 |