1 回答

TA貢獻(xiàn)1811條經(jīng)驗(yàn) 獲得超4個贊
根據(jù)您的需要,此處提供三個可能適合您的選項(xiàng)。
選項(xiàng) 1:已發(fā)布項(xiàng)目的通用界面
不僅為可以擁有訂閱者的發(fā)布者創(chuàng)建一個接口,而且為那些發(fā)布者可以發(fā)布的東西創(chuàng)建一個接口:
type Item interface{
Description() string
Age() int
}
type human struct{
age int
}
func (h *human) Description() string {
return "human"
}
func (h *human) Age() int {
return h.age
}
type Publisher interface{
Subscribe(func(Item))
}
type humanProducer struct{
subscribers []func(Item)
}
func (hp *humanProducer) Subscribe(f func(Item) {
hp.subscribers = append(hp.subscribers, f)
}
// Example use
func addSubscriber(p Publisher, f func(Item)) {
p.Subscribe(f)
}
func main() {
hp := &humanProducer{}
addSubscriber(p, func(i Item) {
fmt.Printf("Got a %s that is %d years old.\n", i.Description(), i.Age())
})
}
您現(xiàn)在可以通過讓它們實(shí)現(xiàn)接口來設(shè)置要發(fā)布的其他類型的東西Item。這里的和方法只是示例——您可以在其中添加任何您需要的方法Description。Age
優(yōu)點(diǎn)
避免反射。
避免類型參數(shù);適用于 Go 1.18 之前的版本。
訂閱者可以接收多種項(xiàng)目。
發(fā)布者可以發(fā)布多種項(xiàng)目。
缺點(diǎn)
已發(fā)布的項(xiàng)目不能只是任何東西——您必須定義一組預(yù)先確定的功能,所有類型的已發(fā)布項(xiàng)目都必須具有這些功能。
已發(fā)布的項(xiàng)目隱藏在界面后面,因此您只能使用界面中公開的功能
Item
,除非您開始強(qiáng)制轉(zhuǎn)換或使用反射。
選項(xiàng) 2:使用類型參數(shù)的接口
將類型參數(shù)添加到接口本身:
type human struct{
age int
}
type Publisher[T any] interface{
Subscribe(func(T))
}
type humanProducer struct{
subscribers []func(*human)
}
func (hp *humanProducer) Subscribe(f func(*human) {
hp.subscribers = append(hp.subscribers, f)
}
// Example use
func addSubscriber[T any](p Publisher[T], f func(T)) {
p.Subscribe(f)
}
func main() {
hp := &humanProducer{}
addSubscriber[*human](p, func(h *human) {
fmt.Printf("Got a human that is %d years old.\n", h.age)
})
}
優(yōu)點(diǎn)
避免反射。
對可以發(fā)布的內(nèi)容沒有限制。
已發(fā)布的項(xiàng)目不會隱藏在界面后面。
缺點(diǎn)
發(fā)布者只能發(fā)布一種特定類型的項(xiàng)目。
訂戶只能收到一種特定的物品。
接口的任何使用都
Publisher
需要使用類型參數(shù)。僅適用于 Go 1.18 或更高版本。
選項(xiàng) 3:反射/鑄造
允許發(fā)布者發(fā)布任何內(nèi)容,并在訂閱者中使用反射或強(qiáng)制轉(zhuǎn)換來確定發(fā)布的內(nèi)容類型:
type human struct{
age int
}
type Publisher interface{
Subscribe(func(any))
}
type humanProducer struct{
subscribers []func(any)
}
func (hp *humanProducer) Subscribe(f func(any) {
hp.subscribers = append(hp.subscribers, f)
}
// Example use
func addSubscriber(p Publisher, f func(any)) {
p.Subscribe(f)
}
func main() {
hp := &humanProducer{}
addSubscriber(p, func(i any) {
if h, ok := any.(*human); ok {
fmt.Printf("Got a human that is %d years old.\n", h.age)
}
})
}
如果使用 1.18 之前的 Go,請?zhí)鎿Qany
為interface{}
. 此選項(xiàng)與選項(xiàng) 1 有點(diǎn)相同,只是Item
接口為空。
優(yōu)點(diǎn)
避免類型參數(shù);適用于 Go 1.18 之前的版本。
對可以發(fā)布的內(nèi)容沒有限制。
已發(fā)布的項(xiàng)目不會隱藏在界面后面。
訂閱者可以接收多種項(xiàng)目。
發(fā)布者可以發(fā)布多種項(xiàng)目。
缺點(diǎn)
需要反射或投射,這是緩慢、笨拙且不太安全的。
訂戶將不得不做額外的工作來弄清楚他們收到了什么樣的項(xiàng)目。
- 1 回答
- 0 關(guān)注
- 144 瀏覽
添加回答
舉報