3 回答

TA貢獻1825條經驗 獲得超6個贊
我會說這歸結為你能控制什么。在您的示例中,您似乎描述了兩個單獨的包。有多種方法可以處理此問題:
接受一個函數
您可以修改ApiFunction以接受處理您想要的情況的功能:
type consumerDeps interface {
ApiFunction(func() string) string
}
這將允許您將您想要的確切功能注入消費者。然而,這里的缺點是這會很快變得混亂,并且會混淆定義函數的意圖,并在實現接口時導致意想不到的后果。
接受接口{}
您可以修改ApiFunction以接受interface{}由實現接口的人處理的對象:
type consumerDeps interface {
ApiFunction(interface{}) string
}
type producer struct{}
type apiFunctionInput interface {
hello() string
}
func (producer) ApiFunction(i interface{}) string {
return i.(apiFunctionInput).hello()
}
這稍微好一點,但現在您依賴于生產者端正確解釋數據,如果它沒有執行此操作所需的所有上下文,那么如果它轉換為,您可能會出現意外行為或恐慌錯誤的類型。
接受第三方接口
您還可以創建一個第三方接口,在這里稱之為適配器,它將定義生產者端和消費者端都可以同意的功能:
type Adapter interface {
hello() string
}
type consumerDeps interface {
ApiFunction(Adapter) string
}
現在,您有一個數據合同,可用于由消費者發送和由生產者接收。這可能像定義一個單獨的包一樣簡單,也可能像整個存儲庫一樣復雜。
重新設計
最后,你可以重新設計你的代碼庫,這樣生產者和消費者就不會像這樣耦合在一起。雖然我不知道您的具體用例,但您遇到這個特定問題這一事實意味著您的代碼耦合得太緊,可能應該重新設計。消費者端和生產者端包之間可能有一個元素拆分,可以提取到第三個包。

TA貢獻1725條經驗 獲得超8個贊
我不太清楚你為什么要介紹這個myRequirements界面。如果Chef需要一個FruittoCut并且你想定義一個特定的水果Apple- 你需要做的就是定義一個Apple實現接口的結構Fruit。
type Chef struct {
}
type fruit interface {
Cut() error
}
func (c Chef) Cut(fruit fruit) error {
return fruit.Cut()
}
然后,您需要做的就是根據您的要求定義Apple實現接口的對象:Fruit
package kitchen
import chef "goplayground/interfaces/fruits/chef"
type Apple struct {
}
func (a Apple) Cut() error {
// lets cut
return nil
}
type myRequirements interface {
Cut(Apple) error
}
type myChef struct {
chef chef.Chef
}
func (m myChef) Cut(apple Apple) error {
// since Apple implements the chef`s fruit interface this is possible
return m.chef.Cut(apple)
}
func cook() {
remy := myChef{}
apple := Apple{}
_ = remy.Cut(apple)
}

TA貢獻1783條經驗 獲得超4個贊
正確使用 duck-typing 有一些細微差別,這就是 Go 類型系統在接口方面的作用。在使用它們的地方定義接口通常是一個好習慣,但io.Reader接口是在標準庫中定義的。因此,該建議的適用性有限。
在你的例子中,包chef有兩個接口,Chef和Fruit. 這兩個接口緊密耦合,因為Chef有一個方法使用Fruit. 使用當前的 Go 類型系統,Chef如果不從該包中導出就無法使用Fruit。所以:
type myRequirements interface {
Cut(chef.Fruit) error
}
是您可以使用包中的實現的chef.Chef唯一方法。Apple
但是你想要做的是:
type myRequirements interface {
Cut(Apple) error
}
并且您希望能夠傳達這是 的子集Chef,也就是說, 的語義Cut與 的語義相同Chef。好吧,語義是不同的。否則是不安全的。
說,你實施Apple為:
type Apple struct {}
func (a Apple) SomeFunc()
func (a Apple) FruitFunc()
而是chef.Fruit:
type Fruit interface {
FruitFunc()
}
顯然,Appleimplements chef.Fruit,因此您可以傳遞到需要Applea 的任何地方。chef.Fruit但是你不能傳遞chef.Fruit給myRequirements.Cut(Apple)函數。因為 in myRequirements.Cutyou 也暗示你可以使用Apple.SomeFunc, which is not defined in chef.Fruit.
所以,如果你真的想定義一個像 的接口myRequirements,那么你必須使用chef.Fruit. 如果你定義的是using Apple,那么myRequirements.Cut方法就不同于chef.Cut。
- 3 回答
- 0 關注
- 173 瀏覽
添加回答
舉報