第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

在 Golang 中,消費(fèi)者如何為接受接口的函數(shù)定義接口?

在 Golang 中,消費(fèi)者如何為接受接口的函數(shù)定義接口?

Go
翻閱古今 2023-02-21 16:49:07
如果我正確理解 Go 實(shí)踐,調(diào)用者(也稱為消費(fèi)者)應(yīng)該從他們的依賴項(xiàng)(也稱為生產(chǎn)者)中定義他們想要使用的接口。但是,如果生產(chǎn)者有一個(gè)接受自定義類型的函數(shù),那么最好讓它接受一個(gè)接口,對(duì)吧?這樣消費(fèi)者就可以傳遞一些符合生產(chǎn)者接口的值,而不知道確切的類型。因?yàn)樯a(chǎn)者函數(shù)的輸入值使生產(chǎn)者成為該輸入值的“消費(fèi)者”。好吧,很公平。問(wèn)題是,消費(fèi)者如何定義一個(gè)接口,其中包含一個(gè)函數(shù),其參數(shù)是生產(chǎn)者定義的接口?試圖使問(wèn)題更清楚假設(shè)我有一個(gè)名為chefstruct 的包Chef。它有一個(gè)方法Cut(fruit) error,fruit是在我的包中定義的一個(gè)接口chef?,F(xiàn)在假設(shè)我在調(diào)用代碼中,我導(dǎo)入了 package chef。我想給它一個(gè)水果來(lái)切,但在我的例子中,我實(shí)現(xiàn)了一個(gè)名為Apple. 自然地,我會(huì)嘗試為自己構(gòu)建這個(gè)界面:type myRequirements interface {   Cut(Apple) error}因?yàn)槲矣薪涌诘木唧w實(shí)現(xiàn)fruit叫Apple,所以我想說(shuō)明我的接口只適用于蘋果。但是,如果我嘗試針對(duì)我的界面使用Chef{},Go 將拋出編譯錯(cuò)誤,因?yàn)槲业慕缑嫦胍狢ut(Apple)和Chef{}想要的Cut(Fruit)。盡管 Apple 實(shí)現(xiàn)了fruit.避免這種情況的唯一方法似乎是制作chef.Fruit一個(gè)公共界面,并在我自己的界面中使用它。type myRequirements interface {   Cut(chef.Fruit) error}但這完全破壞了我在接口下插入不同實(shí)現(xiàn)(而不是chef)的能力,因?yàn)楝F(xiàn)在我與chef.所以 Chef 有一個(gè)內(nèi)部接口fruit,但調(diào)用者只知道 Apple。我如何在調(diào)用者的界面中指示應(yīng)該輸入什么Cut而不引用chef?回答評(píng)論“你為什么需要 myRequirements?”我很驚訝這不是 Go 社區(qū)中更一致的概念。我需要 myRequirements 接口的原因是因?yàn)槲沂?chef 包的消費(fèi)者。此外Cut,廚師可能還有100多種方法。但我只使用Cut. 我想向其他開發(fā)人員表明,在我的情況下,我只使用Cut. 我還想讓測(cè)試只模擬Cut我的代碼工作。此外,我需要能夠插入不同的實(shí)現(xiàn)Cut(來(lái)自不同的廚師)。這是我帖子開頭提到的 golang 最佳實(shí)踐。
查看完整描述

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è)包。


查看完整回答
反對(duì) 回復(fù) 2023-02-21
?
qq_遁去的一_1

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)

}


查看完整回答
反對(duì) 回復(fù) 2023-02-21
?
慕娘9325324

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。


查看完整回答
反對(duì) 回復(fù) 2023-02-21
  • 3 回答
  • 0 關(guān)注
  • 181 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)