我想定义一个接口,该接口的方法返回一个类型为接口本身的值。
我试图这样定义接口:
type Event interface {
}
type Entity interface {
ApplyEvent(command Event) (Entity, error)
}
我想通过以下方式使结构实现Entity接口:
type ShoppingList struct {
}
func (list ShoppingList) ApplyEvent(event Event) (ShoppingList, error) {
// code that changes "list" goes here.
return list, nil
}
如果我这样做,然后尝试将ShoppingList传递给需要实体的函数,则会出现以下错误:
func main() {
test(ShoppingList{})
}
func test(e Entity) {
}
Cannot use 'ShoppingList{}' (type ShoppingList) as type Entity.
Type does not implement 'Entity'
need method: ApplyEvent(command Event) (Entity, error)
have method: ApplyEvent(event Event) (ShoppingList, error)
我知道我可以这样定义接口和接收器:
type Event interface {
}
type Entity interface {
ApplyEvent(command Event) error
}
type ShoppingList struct {
}
func (list *ShoppingList) ApplyEvent(event Event) error {
// code that changes "list" goes here.
return nil
}
但是我更愿意使用纯函数和不可变数据结构来编写代码。
我想返回更改后的值,而不是使接收方发生变化。
在Go中执行此操作的方式是什么?
答案 0 :(得分:1)
似乎您可能已经知道这一点。但是以防万一您还没有想到它,您也可以这样写:
type Event interface {
}
type Entity interface {
ApplyEvent(command Event) (Entity, error)
}
type ShoppingList struct {
}
func (list ShoppingList) ApplyEvent(event Event) (Entity, error) {
//...
return list
}
在这里,我做的是相同的return
,但我将其作为Entity
接口而不是ShoppingList
返回。如果稍后将Entity
用作购物清单是有意义的,如果我想在代码的后面查看Entity
是否是ShoppingList
,则可以尝试进行类型断言。
但是,为interface
提供一种接口方法,使ShoppingList
能够做到其事,是因为它是 Entity 而不是消费者列举所有可能的实体。毕竟,为什么将“事件”应用于“ ShoppingList”的过程中必然会产生另一个“ ShoppingLIst”?它不能生成例如InstacartInvoice吗?当然,在这一点上,我已经超出了您的问题范围。但是,只要接口的具体值的类型与使用者有关,就必须非常努力地使其与该接口的方法有关。就像您使用ApplyEvent
一样。