Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 不改变接收器的接口_Go - Fatal编程技术网

Go 不改变接收器的接口

Go 不改变接收器的接口,go,Go,我想定义一个接口,该接口有一个方法,该方法返回一个类型为接口本身的值 我试图这样定义接口: type Event interface { } type Entity interface { ApplyEvent(command Event) (Entity, error) } type Event interface { } type Entity interface { ApplyEvent(command Event) (Entity, error) } type S

我想定义一个接口,该接口有一个方法,该方法返回一个类型为接口本身的值

我试图这样定义接口:

type Event interface {
}

type Entity interface {
    ApplyEvent(command Event) (Entity, error)
}
type Event interface {
}

type Entity interface {
    ApplyEvent(command Event) (Entity, error)
}

type ShoppingList struct {
}

func (list ShoppingList) ApplyEvent(event Event) (Entity, error) {
    //...
    return list
}
我希望通过以下操作使结构实现实体接口:

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
}
但是我更喜欢尽可能使用纯函数和不可变的数据结构来编写代码

我想返回更改后的值,而不是改变接收器


在围棋中怎么做?

看来你可能已经知道了这一点。但万一你还没想到,你也可以这样写:

type Event interface {
}

type Entity interface {
    ApplyEvent(command Event) (Entity, error)
}
type Event interface {
}

type Entity interface {
    ApplyEvent(command Event) (Entity, error)
}

type ShoppingList struct {
}

func (list ShoppingList) ApplyEvent(event Event) (Entity, error) {
    //...
    return list
}
在这里,我做的是相同的
返回
,但我将其作为
实体
界面而不是
购物列表
返回。如果与
实体
以后是一个购物列表相关,如果我想查看
实体
在代码中是否是一个
购物列表
,我可以尝试类型断言


但是,为
购物清单
提供一种接口方法更符合
接口
的概念,因为它是一个实体,而不是消费者列举所有可能的实体。毕竟,为什么应用于“购物清单”的“事件”必然会产生另一个“购物清单”?例如,它不能生成InstacartInvoice吗?当然,在这一点上,我远远超出了你问题的范围。但是,每当接口的具体值的类型与使用者相关时,都要努力使其与该接口的方法相关。就像您在
ApplyEvent

中所做的那样,您并没有真正实现该功能。接口函数的签名是:
ApplyEvent(command-Event)(Entity,error)
,对于
ShoppingList
它是
ApplyEvent(Event-Event)(ShoppingList,error)
(它需要返回一个
Entity
,不能保证是相同的具体类型。)……换句话说,补充一下其他人所说的:Go既没有“泛型”(C#-或Java风格)也没有“模板”(C++风格)。不过到了v2.0,它很可能会有泛型。Go的接口是非常真实的值,而不是某种“参数化”的抽象占位符。我强烈推荐一位Go开发者;文档有点生疏(Go不再将指针大小的值直接嵌入到接口值中),但清晰明了,切中要害。我是新手,我想我正在努力解决的问题是,如何定义一个可以在以后专门化的通用具体行为?在Java或Typescript中,您将定义一个具有泛型行为的类和应由子类实现的抽象方法。Go
接口有点像一个抽象类,它定义了方法的签名,但没有定义它们。然而,相似之处到此为止。通过扩展抽象基类来组合具体类的想法更像是嵌入结构()。