我有一个很大的Go程序,它分布在我的包文件夹根目录中的50多个杂项Go文件中。我知道这被认为是可怕的,所以我决定将程序拆分成一些子包以便更好地组织。
不幸的是,在将程序的逻辑部分拆分为子包之后,我遇到了可怕的“导入循环不允许”错误。这是因为Go编译器拒绝使用循环导入编译任何内容。但是我的程序的不同逻辑部分需要相互通信......
我在网上做了一些研究,发现了一些优秀的资源,比如this excellent StackOverflow question,试图解释在高层次上解决这个问题的想法。
我很抱歉,但是这篇文章已经超出了我的想法,我想知道是否有人可以为我的特定代码情况拼出一个确切的解决方案,希望用更简单的语言来完成初学者Go。
我的代码组织方式及其作用的简要说明:
main.go
文件中初始化所有这些子包。答案 0 :(得分:2)
看起来您希望将协议特定代码保存在单独的包中。
如果您不想要太多重构,我建议您使用dispatcher
创建一个包。每个服务器都导入dispatcher
包并注册特定协议的处理程序。当需要调用另一台服务器时,只需通过dispatcher
向指定的处理程序发送消息。
答案 1 :(得分:1)
根据您的具体情况量身定制:
根据您的描述,程序包相互导入的唯一原因是他们需要相互调用Send()
函数。
在main中创建频道,并将其提供给init上的两个软件包。然后他们可以在不知道彼此存在的情况下相互沟通。
答案 2 :(得分:1)
除了TechSphinX和Oleg提出的基于通道的方法之外,您还可以使用基于接口的方法和简单的依赖注入。
您可以使用可能在main()
中或从Send()
调用的设置功能来创建每个服务客户端的实例。这些应该每个都实现Sender
并为他们需要使用的其他客户端提供字段。在自己的包中创建一个// pkg sender
type Sender interface {
Send(m Message) error // or whatever it needs to be
}
type Message struct {
// Whatever goes in a message
}
type Dispatcher struct {
TwitchClient Sender
DiscordClient Sender
WebClient Sender
}
// pkg main
func setup() {
d := sender.Dispatcher{
TwitchClient: twitch.New(),
DiscordClient: discord.New(),
WebClient: web.New(),
}
d.TwitchClient.Dispatcher = d
d.DiscordClient.Dispatcher = d
d.WebClient.Dispatcher = d
}
// pkg twitch
type TwitchClient struct {
Dispatcher sender.Dispatcher
// other fields ...
}
func New() *TwitchClient {
return new(TwitchClient) // or whatever
}
func (t *TwitchClient) Send(m sender.Message) error {
// send twitch message...
// Need to send a Discord message?
t.Dispatcher.DiscordClient.Send(m)
}
接口,并将消息结构放在那里。
创建实例后,您可以在每个实例上设置其他客户端。通过这种方式,他们可以发送到他们需要发送的任何内容,而不需要循环依赖。您甚至可以将所有客户端放入结构中以使注入更容易。
例如:
@Autowired
ServletContext context;
答案 3 :(得分:1)
听起来服务器/协议包本身很有用,并且要求将消息从一种服务器发送到另一种服务器是您特定应用程序的一项功能。换句话说,服务器/协议包不需要彼此发送消息,应用程序需要。
我通常会将特定于应用程序的功能放入应用程序包中。包应用可以导入所有协议包。
您也可以在主程序包中执行此操作,但我发现应用程序包是更有用的工具。 (我的主要包通常只是单个main.go文件。)