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