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

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

使用接口作為參數(shù)創(chuàng)建另一個(gè)包的等效接口

使用接口作為參數(shù)創(chuàng)建另一個(gè)包的等效接口

Go
吃雞游戲 2023-04-04 15:11:51
我正在練習(xí)編寫慣用的 Go 代碼,發(fā)現(xiàn)接口應(yīng)該在使用它們的包中聲明,因?yàn)樗鼈兪请[式的。但是我遇到了這種情況,在第二個(gè)包(包 b)中,我想要一個(gè)函數(shù)來調(diào)用包 a 中的結(jié)構(gòu)的接收函數(shù),而不緊密耦合它。所以很自然地,我在包 b 中聲明了一個(gè)接口,其中包含我想從包 a 調(diào)用的函數(shù)的簽名。問題是這個(gè)函數(shù)接受一個(gè)特定類型的參數(shù),這個(gè)參數(shù)是在包 a 中聲明的接口。因?yàn)槲也幌M?b 導(dǎo)入包 a,所以我在包 b 中定義了一個(gè)接口,其簽名與包 a 中存在的簽名完全相同。下面的 playground 鏈接顯示了示例代碼。操場package mainimport (    "fmt"    "log")func main() {    manager := &Manager{}    coach := NewRunnerCoach(manager)    fmt.Println("Done")}// package atype Runner interface {    Run()}type Manager struct {}func (o *Manager) RegisterRunner(runner Runner) {    log.Print("RegisterRunner")}func (o *Manager) Start() {    log.Print("Start")}// package btype RunnerCoach struct {    runner *FastRunner}func NewRunnerCoach(registerer runnerRegisterer) *RunnerCoach {    runnerCoach := &RunnerCoach{&FastRunner{}}    registerer.RegisterRunner(runnerCoach.runner)    return runnerCoach}type FastRunner struct {}func (r *FastRunner) Run() {    log.Print("FastRunner Run")}// define ther registerer interface coach is acceptingtype runnerRegisterer interface {    RegisterRunner(runner RunnerB)}// declaring a new interface with the same signature because we dont want to import package a// and import Runner interfacetype RunnerB interface {    Run()}此代碼無法編譯。所以這里的問題是,我是在錯(cuò)誤地使用接口,還是應(yīng)該在單獨(dú)的包中定義具體類型,或者最后,是否有更好的代碼模式來解決我要解決的問題?編輯:澄清一下,包 a 和 b 不會(huì)相互導(dǎo)入。main() 代碼存在于連接這兩者的單獨(dú)包中。
查看完整描述

2 回答

?
慕容3067478

TA貢獻(xiàn)1773條經(jīng)驗(yàn) 獲得超3個(gè)贊

IIUC,你的問題不是關(guān)于包,而是歸結(jié)為一個(gè)函數(shù)(或方法)是否可以類型轉(zhuǎn)換為另一個(gè)函數(shù),該函數(shù)接受具有等效但不同接口類型的參數(shù)。

像這樣的東西:

package main


type I1 interface{}


func f1(x I1) {}


func main() {

? ? f := (func(interface{}))(f1)

? ? f(nil)

}

編譯錯(cuò)誤:?./g.go:8:26: cannot convert f1 (type func(I1)) to type func(interface {})

答案似乎是否定的,因?yàn)?Go 不認(rèn)為func (I1)等同于func (interface{}).?Go規(guī)范是這樣說的

函數(shù)類型表示具有相同參數(shù)和結(jié)果類型的所有函數(shù)的集合。

類型func (I1)func (interface{})不采用相同的參數(shù),即使?I1定義為interface{}.?由于類似的原因,您的代碼無法編譯,因?yàn)?code>func (runner RunnerB)它不相同func (runner Runner),因此方法集?*Manager不是接口的超集runnerRegisterer。

回到你原來的問題:

我正在練習(xí)編寫慣用的 Go 代碼,發(fā)現(xiàn)接口應(yīng)該在使用它們的包中聲明,因?yàn)樗鼈兪请[式的。

是的,這個(gè)想法很好,但它并不像您認(rèn)為的那樣適用于您的實(shí)施。由于您期望有不同的實(shí)現(xiàn),?runnerRegisterer并且它們都必須具有使用接口的具有相同簽名的方法,因此在公共位置Runner定義是有意義的。Runner此外,如上所示,無論如何,Go 不允許您在方法簽名中使用不同的接口。

根據(jù)我對您要實(shí)現(xiàn)的目標(biāo)的理解,以下是我認(rèn)為您應(yīng)該重新安排代碼的方式:

  1. 定義RunnerRegisterer(注意:這是公開的)并Runner在一個(gè)包中。

  2. 在同一個(gè)包中實(shí)現(xiàn)您的RunnerCoach并使用上述接口。您RunnerCoach使用實(shí)現(xiàn)接口的類型,因此它定義了它們。

  3. 在另一個(gè)包中實(shí)施您的跑步者。您不在Runner?此處定義接口。

  4. 在另一個(gè)包中實(shí)現(xiàn)你的,它使用在 的包中定義的Manager接口?,因?yàn)槿绻胗米?RunnerRunnerCoachRunnerRegisterer


查看完整回答
反對 回復(fù) 2023-04-04
?
呼喚遠(yuǎn)方

TA貢獻(xiàn)1856條經(jīng)驗(yàn) 獲得超11個(gè)贊

解決方案

您有一個(gè)類型在兩個(gè)包 A 和 B 中使用。包 A 導(dǎo)入包 B。

你必須避免循環(huán)依賴,所以你有三個(gè)選擇:

  1. 在包 B 中定義類型,因此它在兩個(gè)包中都可用。

  2. 在包 C 中定義類型,讓 A 和 B 都導(dǎo)入包 C。

  3. 更改您的設(shè)計(jì),使 A 和 B 中都不使用該類型。

無論該類型是接口還是任何其他類型,這些都是您的選擇。

選擇最適合您的設(shè)計(jì)目標(biāo)的選項(xiàng)。

規(guī)則/成語

我正在練習(xí)編寫慣用的 Go 代碼,發(fā)現(xiàn)接口應(yīng)該在使用它們的包中聲明,因?yàn)樗鼈兪请[式的。

我有了沖動(dòng)/想法——問題是它不太實(shí)用。如果接口只能在定義它們的包中使用,那么它們的用處就會(huì)小一些。標(biāo)準(zhǔn)庫中充滿了違反這條公理的代碼。因此,我不認(rèn)為所提出的規(guī)則——適用于所有情況、設(shè)計(jì)和上下文中的所有界面——是慣用的。

例如,查看bytes包。?func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error)consumes?io.Reader,在另一個(gè)包中定義的接口。?func (r *Reader) WriteTo(w io.Writer) (n int64, err error)consumes?io.Writer,在另一個(gè)包中定義的接口。


查看完整回答
反對 回復(fù) 2023-04-04
  • 2 回答
  • 0 關(guān)注
  • 127 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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