请教下用这种方式解决 import cycle 有什么弊端吗?

2022-07-30 08:02:31 +08:00
 fujianjian
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 不引任何包, 这样的做有什么问题吗?

1640 次点击
所在节点    Go 编程语言
9 条回复
sadfQED2
2022-07-30 10:16:31 +08:00
你这个难道能编译通过? GetA 不是一个函数吗,你怎么能给函数赋值?
jinliming2
2022-07-30 11:08:27 +08:00
@sadfQED2 GetA 看着是个函数指针啊?😯
janxin
2022-07-30 14:02:44 +08:00
可以是可以,但是你未来很难保证你的这个包只有函数和基本类型吧
fujianjian
2022-07-30 15:28:51 +08:00
@janxin 是的, 但是包里有几个方法很难再拆包了, 社交的业务代码比较杂乱, 暂时采取这种丑陋的方式
katsusan
2022-07-30 18:22:37 +08:00
mauve
2022-07-31 20:03:31 +08:00
也许不用写这么复杂,这不就是个全局变量吗?
用全局变量解决 import cycle 好吗?不好
fujianjian
2022-07-31 22:19:22 +08:00
@katsusan 我上面写的办法应该跟 cockroachdb 的 Dependency injection 的方案是类似的 :)
fujianjian
2022-07-31 22:20:25 +08:00
@mauve 所以也一直觉得比较丑陋, 但是更好的办法也还没找到
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 吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/869588

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX