我意識到之前已經回答了有關循環依賴的問題,但是,答案通常只是說合并包。長話短說,我有一個可以實現多種類型的接口。我想有一種方法來使用其名稱選擇在運行時使用其中一種類型。這也將用于序列化。我讀入類的名稱,然后實例化正確的類。我使用了策略模式。Basepackage 中有一個接口A。package Aimport ( "../C")type Base interface { doStuff(p C.Profile) int}type Operation struct { Base Base Data int}func (o *Operation) execute(p C.Profile) int { return o.Base.doStuff(p)}然后,在 package 中有實現該接口的類型B。//file Impl1.gopackage Bimport ( "../C")type Impl1 struct {}func (b *Impl1 ) doStuff(p C.Profile) int { ...}//file Impl2.gopackage Bimport ( "../C")type Impl2 struct {}func (b *Impl2 ) doStuff(p C.Profile) int { ...}然后在包中C我有Foo一個類型為 struct 的字段Base。該字段可以指向 package 中的任何實現B。我們可以在運行時選擇實現。這是我最終想要序列化的結構。package Cimport ( "../A" "../B") type Foo struct { bar A.Base baz []Profile ...}func (f *Foo) changeBar(name string, data int) { switch name { case "Impl1": f.bar = Operation{Base: B.Impl1{}, Data: data} case "Impl2": f.bar = Operation{Base: B.Impl2{}, Data: data} ...}編輯:同樣在C包中,我們有,Profile這就是包需要導入它的原因。AB此代碼具有循環依賴關系C-> B-> C。一個明顯的解決方案是移動Profile到不同的包。但這是不可能的,因為Profile(以及包中的許多其他類似類型C)并且Foo非常緊密地耦合并且屬于同一個包(在這個最小的工作示例中可能不那么明顯)。這是此類問題的其他答案所暗示的,但我想學習如何使用從使用其他語言中學到的良好實踐來使其發揮作用。另一種解決方案是以某種方式將工廠方法移動changeBar到另一個包并僅在包外部使用它C(從而避免循環),將其結果C作為參數傳遞,但在某些情況下(特別是序列化)我實際上需要它在C包裝的內側。我花了很多時間來解決這個問題,但我最終的結果是要么將所有內容放在一個巨大的包中,要么將每個文件放在一個單獨的包中并導出所有內容。在其他編程語言中,有可能要么有這些循環依賴,要么一次從包中導入一個“類”。進去的方法是什么?
1 回答

臨摹微笑
TA貢獻1982條經驗 獲得超2個贊
您可以使用類型注冊表打破從 C 到 B 的依賴關系:
package C
import "A"
var TypeRegistry = map[string]func() A.Base {}
func (f *Foo) changeBar(name string, data int) {
if factory, ok:=TypeRegistry[name]; ok {
f.bar=Operation{Base:factory(),Data:data}
}
}
然后在任何包中注冊您的實現:
package B
import "../C"
func init() {
C.TypeRegistry["myType"]=func() A.Base { return MyType{}}
}
- 1 回答
- 0 關注
- 204 瀏覽
添加回答
舉報
0/150
提交
取消