在Golang中使用结构进行循环导入

the*_*eva 10 circular-dependency go

我在Golang有一个包含几个模块的项目.由于以下场景,我遇到循环导入问题:

细节

模块游戏包含具有当前游戏状态的结构.另一个模块(Modifier)正在做一些游戏特定的东西和计算,因此修改了游戏状态.因此,Modifier将需要struct Game,但不需要来自Game的任何方法.从Game中调用修饰符,这里我们有循环导入.

问题:

  • 游戏启动修改器

  • 修饰符需要Game结构

在我看来,这是一个常见的场景,所以我想知道我应该如何以最好的方式解决它.我的解决方案是创建第三个模块"Structs",它只包含整个应用程序的所有结构.这是一个好的解决方案吗?

Dav*_*e C 0

通常,如果包中B有直接读取/修改的代码A.Type,那么该代码应该位于包中A。\n如果需要直接访问,至少应该包含其中的部分。

\n\n

要在不同的包之间拆分某些内容AB您通常会尝试隔离 API 以访问A.Type可以表示为接口的 API。然后B定义并使用这个接口并A.Type实现它(隐式地,不需要包含 B 的定义)。

\n\n

然后某些东西(可能是,可能是一个单独的包)将通过适当地传递or值来A使用。BA.Type*A.Type

\n\n

或者根据您的设计,关系可以颠倒,B.OtherType隐式实现由 定义和使用的接口A。\nA或者两者都B只能通过接口相互使用;这一切都取决于细节。

\n\n

例如也许是这样的:

\n\n
package Game // "A"\n\ntype State struct {\n        data int // etc\n}\n\nfunc (s State) IsValid() bool          { return true }\nfunc (s *State) ChangeY(arg int) error { return nil }\n// \xe2\x80\xa6etc\xe2\x80\xa6\n
Run Code Online (Sandbox Code Playgroud)\n\n

和:

\n\n
package Modifier // "B"\n\ntype GameState interface {\n        IsValid() bool\n        ChangeY(int) error\n}\n\ntype M struct {\n        s GameState\n        //\xe2\x80\xa6\n}\n\nfunc New(s GameState) *M {\n        return &M{s: s}\n}\n\nfunc (m M) DoSomething() {\n        if s.IsValid() {\n                // \xe2\x80\xa6\n        }\n        s.ChangeY(42)\n        // \xe2\x80\xa6etc\xe2\x80\xa6\n}\n
Run Code Online (Sandbox Code Playgroud)\n