我正在寫一個 go 模組,它實作一個滿足介面的結構。我們只想維護庫的單一版本,但我們的客戶使用我們的依賴項之一的多個版本。
依賴項提供了我們想要實現的接口,如下所示。
type supercoolinterface interface { dooldcoolthing(value string) }
我們的實作是這樣的。
type supercoolimpl struct {} func (sc *supercoolimpl) dooldcoolthing(value string) {}
新版本的依賴項在類型模組中新增了新類型。
type newtype struct { value string }
依賴項為介面新增了一個方法。
type supercoolinterface interface { dooldcoolthing(value string) donewcoolthing(value types.newtype) }
現在,如果我實作新方法,它將無法使用舊版的函式庫進行編譯,因為 types.newtype
不存在。但是,如果我不實作新版本,我就無法滿足新版本的介面。
type SuperCoolImpl struct {} func (sc *SuperCoolImpl) DoOldCoolThing(value string) {} func (sc *SuperCoolImpl) DoNewCoolThing(value types.NewType) {}
我們是否需要分叉程式碼才能支援此版本?在具有預處理器的語言中,有一個簡單的解決方案,所以我假設 go 一定有一個我缺少的解決方案。
我們計劃繼續開發並支援這兩個版本,因此需要確保兩個不同版本保持一致性會很煩人。我希望我可以用反射或類似於 c 預處理器的東西來做一些事情,在其中我可以定義一個預處理器值,並且僅當我們指示庫的版本具有正確的類型時才實現該方法。
我找到了適合我的情況的解決方案。
感謝@Burak Serdar 為我指明了正確的方向。
我的解決方案是將舊的實作放入 impl/v0 套件中,將新的實作放入 impl/v1 套件中。
使用舊版相依性的用戶端將使用 impl/v0,使用新版本相依性的用戶端將使用 impl/v1。
由於golang只編譯直接導入的程式碼,所以只有介面版本正確的套件才會被編譯,所以雙向都會編譯成功。
這減輕了我對必須分叉整個函式庫的擔憂。
編輯:如果有人使用此解決方案,如果您目前正在使用 go test ./...
執行測試,則會出現一個問題。該命令似乎嘗試建立每個模組,無論它是否包含測試。
但是您可以使用go test $(go list ./... | grep -v <path_to_ignore>)</path_to_ignore>
排除測試,然後您可以在另一個命令中針對正確的版本執行這些測試。
以上是如何支援同一介面的多個版本?的詳細內容。更多資訊請關注PHP中文網其他相關文章!