3 回答

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

TA貢獻(xiàn)1725條經(jīng)驗(yàn) 獲得超8個(gè)贊
我不太清楚你為什么要介紹這個(gè)myRequirements界面。如果Chef需要一個(gè)FruittoCut并且你想定義一個(gè)特定的水果Apple- 你需要做的就是定義一個(gè)Apple實(shí)現(xiàn)接口的結(jié)構(gòu)Fruit。
type Chef struct {
}
type fruit interface {
Cut() error
}
func (c Chef) Cut(fruit fruit) error {
return fruit.Cut()
}
然后,您需要做的就是根據(jù)您的要求定義Apple實(shí)現(xiàn)接口的對(duì)象: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貢獻(xiàn)1783條經(jīng)驗(yàn) 獲得超4個(gè)贊
正確使用 duck-typing 有一些細(xì)微差別,這就是 Go 類型系統(tǒng)在接口方面的作用。在使用它們的地方定義接口通常是一個(gè)好習(xí)慣,但io.Reader接口是在標(biāo)準(zhǔn)庫(kù)中定義的。因此,該建議的適用性有限。
在你的例子中,包c(diǎn)hef有兩個(gè)接口,Chef和Fruit. 這兩個(gè)接口緊密耦合,因?yàn)镃hef有一個(gè)方法使用Fruit. 使用當(dāng)前的 Go 類型系統(tǒng),Chef如果不從該包中導(dǎo)出就無(wú)法使用Fruit。所以:
type myRequirements interface {
Cut(chef.Fruit) error
}
是您可以使用包中的實(shí)現(xiàn)的chef.Chef唯一方法。Apple
但是你想要做的是:
type myRequirements interface {
Cut(Apple) error
}
并且您希望能夠傳達(dá)這是 的子集Chef,也就是說(shuō), 的語(yǔ)義Cut與 的語(yǔ)義相同Chef。好吧,語(yǔ)義是不同的。否則是不安全的。
說(shuō),你實(shí)施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)函數(shù)。因?yàn)?in myRequirements.Cutyou 也暗示你可以使用Apple.SomeFunc, which is not defined in chef.Fruit.
所以,如果你真的想定義一個(gè)像 的接口myRequirements,那么你必須使用chef.Fruit. 如果你定義的是using Apple,那么myRequirements.Cut方法就不同于chef.Cut。
- 3 回答
- 0 關(guān)注
- 181 瀏覽
添加回答
舉報(bào)