2 回答

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)該重新安排代碼的方式:
定義
RunnerRegisterer
(注意:這是公開的)并Runner
在一個(gè)包中。在同一個(gè)包中實(shí)現(xiàn)您的
RunnerCoach
并使用上述接口。您RunnerCoach
使用實(shí)現(xiàn)接口的類型,因此它定義了它們。在另一個(gè)包中實(shí)施您的跑步者。您不在
Runner
?此處定義接口。在另一個(gè)包中實(shí)現(xiàn)你的,它使用在 的包中定義的
Manager
接口?,因?yàn)槿绻胗米?Runner
RunnerCoach
RunnerRegisterer

TA貢獻(xiàn)1856條經(jīng)驗(yàn) 獲得超11個(gè)贊
解決方案
您有一個(gè)類型在兩個(gè)包 A 和 B 中使用。包 A 導(dǎo)入包 B。
你必須避免循環(huán)依賴,所以你有三個(gè)選擇:
在包 B 中定義類型,因此它在兩個(gè)包中都可用。
在包 C 中定義類型,讓 A 和 B 都導(dǎo)入包 C。
更改您的設(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è)包中定義的接口。
- 2 回答
- 0 關(guān)注
- 127 瀏覽
添加回答
舉報(bào)