亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

當有接口及其在不同包中的實現時如何管理循環依賴

當有接口及其在不同包中的實現時如何管理循環依賴

Go
幕布斯6054654 2022-07-11 17:35:41
我的項目結構如下所示:代碼結構:hypervisor├── hypervisor.go├── hyperv│   └── hyperv.go└── virtualbox    ├── vbox.go    └── vboxprops.go源代碼://hypervisor/hypervisor.gopackage hypervisortype Hypervisor interface {    Start(vmName string) error    ListMounts(vmName string) ([]MountPath, error)    //....}type MountPath struct {    HostPath  string    GuestPath string}func detect() (Hypervisor, error) {    return &virtualbox.Virtualbox{}, nil  // <<1 HERE}// ... other code并有另一個(嵌套)包://hypervisor/virtualbox/vbox.gopackage virtualboxtype Virtualbox struct {}func (*Virtualbox) Start(vmName string) error {    return vboxManage("startvm", vmName, "--type", "headless").Run()}func (*Virtualbox) ListMounts(vmName string) ([]hypervisor.MountPath, error) { // <<2 HERE    // ....} // ... other code正如所見,當然,這樣的代碼會導致import cycle not allowed . 因為:hypervisorpcakge 引用virtualbox.VirtualBox類型virtualbox包引用hypervisor.MountPath類型我知道如果我將結構移動MounthPath到另一個包會解決問題,但我認為這不是正確的解決方案設計方式。有什么建議嗎?
查看完整描述

2 回答

?
素胚勾勒不出你

TA貢獻1827條經驗 獲得超9個贊

例如,我會做的一種最簡單的方法是將實體分成entities包(在這種情況下:HypervisorVirtualbox結構是實體或任何你想調用的東西)。
這是我認為最常見的設計,因此內部包使用的每個結構都不會導致循環依賴。
使用示例:所有time包結構都在頂級包級別。time.Time{},time.Duration{}time.Duration不在time/duration包裝上。

查看完整回答
反對 回復 2022-07-11
?
眼眸繁星

TA貢獻1873條經驗 獲得超9個贊

在大多數情況下,按照 Dave Cheney 的建議來定義調用者的接口將避免循環依賴。但這只會解決平面數據模型。在您的情況下,您有嵌套實體,即 HyperVisor 具有返回 MounthPath 的功能。我們可以通過兩種方式對此進行建模

  1. 在單獨的包中定義 MouthPath(如您建議的那樣)。此外,從長遠來看,在 virtualbox 包中定義接口將有助于為 Hypervisor 提供替代實現。

  2. 讓 virtualbox 將 Hypervisor 和 MounthPath 都定義為接口。一個缺點是管理程序實現包使用 virtualbox.MouthPath 接口來滿足如下傳遞時的接口。

//hypervisor/hypervisor.go


package hypervisor


type Hypervisor struct{

     someField []virtualbox.MountPath

}


type MountPath struct { // this can be used as virtualbox.MountPath

    hostPath  string

    guestPath string

}


func (m *MountPath) HostPath() string { return m.hostPath }

func (m *MountPath) GuestPath() string { return m.guestPath }


func detect() (Hypervisor, error) {

    return &virtualbox.Virtualbox{}, nil  // <<1 HERE

}

并有另一個包(不需要嵌套)


//hypervisor/virtualbox/vbox.go

package virtualbox


type Hypervisor interface {

    Start(vmName string) error


    ListMounts(vmName string) ([]MountPath, error)


    //....


type MountPath interface {

        HostPath()  string

        GuestPath() string

}


type Virtualbox struct {}


func (*Virtualbox) Start(vmName string) error {

    return vboxManage("startvm", vmName, "--type", "headless").Run()

}


func (*Virtualbox) ListMounts(vmName string) ([]MountPath, error) { // <<2 HERE

    // ....


查看完整回答
反對 回復 2022-07-11
  • 2 回答
  • 0 關注
  • 181 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號