2 回答

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

TA貢獻1873條經驗 獲得超9個贊
在大多數情況下,按照 Dave Cheney 的建議來定義調用者的接口將避免循環依賴。但這只會解決平面數據模型。在您的情況下,您有嵌套實體,即 HyperVisor 具有返回 MounthPath 的功能。我們可以通過兩種方式對此進行建模
在單獨的包中定義 MouthPath(如您建議的那樣)。此外,從長遠來看,在 virtualbox 包中定義接口將有助于為 Hypervisor 提供替代實現。
讓 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
// ....
}
- 2 回答
- 0 關注
- 181 瀏覽
添加回答
舉報