duanhuayong6687 2018-12-03 01:06
浏览 12

周期性进口和缺乏仿制药引起头痛

Say I have these two files in golang:

// main/a/a.go
import "main/b"

type Model struct {
    ID         int    `json:"id"`
    Me         int    `json:"me"`
    You        int    `json:"you"`
}

func zoom(v b.Injection){

}

func Start(){
  // ...
}

and then the second file looks like:

// main/b/b.go
import "main/a"

type Injection struct {
    ModelA a.Model
}


func GetInjection() Injection {
    return Injection{
        ModelA: a.Start(),
    }
}

so as you can see, these are circular imports, each file imports the other. So I need to use a 3rd file, and have these two files import the 3rd file.

But I am really struggling how to get this functionality and avoid cyclic imports.

My first step, is to move the Injection type into a 3rd file:

   // main/c/c.go

    type Injection struct {
        ModelA interface{} // formerly a.Model
    }

so now this is what it looks like:

a imports c
b imports a,c

so no more cycles, however the problem is that I don't know how to create an interface for a.Model in c.go? An empty interface{} like I used above doesn't work, for the normal reasons.

How do I solve this cyclic import problem with these 2 original files?

  • 写回答

1条回答 默认 最新

  • douan3414 2018-12-03 01:36
    关注

    If you want them to put into separate packages, you can't have Model and zoom() in the same package, as zoom() refers to Injection and Injection refers to Model.

    So a possible solution is to put Model into package a, zoom() into package b, and Injection into package c. c.Injection can refer to a.Model, b.zoom() can refer to c.Injection. There's no circle in this:

       b.zoom() -------->   c.Injection ---------> a.Model
    

    I assume there are other references in your real code which are not in the question which may prevent this from working, but you can move "stuff" around between packages, or you can break it down into more.

    Also, if things are coupled this "tight", you should really consider putting them into the same package, and then there is no problem to solve.

    Another way to solve circular import issue is to introduce interfaces. E.g. if your zoom() function would not refer to Injection, the package containing Model and zoom() would not need to refer to Injection's package.

    Inspect what zoom() needs to do with Injection. If that is method calls, that's already good. If not, add methods to Injection. Then you may define an interface in zoom()'s package containing the methods zoom() needs to call, and change its parameter type to this interface. Implementing interfaces in Go is implicit, there is no declaration of intent. So you can remove the reference in the parameter type, still you will be able to pass Injection values to zoom().

    Also related, check Dave Cheney's thoughts about organizing code:

    I believe code should be organised into packages names for what the package provides, not what it contains. This can sometimes be subtle, but usually not.

    For example, http, provides http clients and servers.

    As a counter example, package utils is a poor name, yes it provides utilities, but you have no idea what from the name, in truth this package is named for what it contains.

    If your project is a library, it should contain one package (excluding examples and possibly utility commands), if it contains more packages, that is a sign that the library is trying to do too many things.

    Prefer to avoid multiple packages by default, only split code by package if there is a clear separation of concerns. In my experience many frustrations with complex and possibly circular package structures are the result of too many packages in a project.

    评论

报告相同问题?

悬赏问题

  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。