go - 接口(interface)具有相同的方法,但被认为是不同的

标签 go

为什么两个具有相同方法的命名接口(interface)被视为不同的接口(interface) - 如何避免这种情况?

假设我们有一个喜欢吃产品的人 (Eater)。他不在乎他吃什么产品,他只想被人指出他可以从哪里买到新产品。换句话说,他想要产品服务,但不关心产品服务会生产什么产品。具体实现中我们会尝试给他吃苹果,所以我们会给他提供appleService。

结果如下:

./main.go:9: cannot use appleService (type *service.AppleService) as type eater.ProductServiceI in function argument:
        *service.AppleService does not implement eater.ProductServiceI (wrong type for New method)
                have New() service.ProductI
                want New() eater.ProductI

接口(interface) service.AppleIeater.AppleI 具有相同的方法 Eat() 并且 golang 将它们视为不同的方法。为什么以及如何避免这种情况?根据鸭子类型,这应该有效,因为 ProductServiceI 实际需要的是提供的结构具有 Eat() 方法 - 它不应该关心什么名称具有接口(interface)( service.ProductIeater.ProductI)。

完整代码如下:

==> ./main.go <==

package main

import "./apple/service"
import "./eater"

func main() {
    appleService := &service.AppleService{}
    // func eater.New(productService ProductServiceI)
    appleEater := eater.New(appleService) 
    appleEater.EatUntilHappy()
}

==> ./eater/eater.go <==

package eater

type ProductServiceI interface {
    New() ProductI
}

type ProductI interface {
    Eat()
}

type Eater struct {
    productService ProductServiceI
}

func New(productService ProductServiceI) *Eater {
    return &Eater{
        productService: productService,
    }
}

func (a *Eater) EatUntilHappy() {
    for i:=0; i < 5; i++ {
        product := a.productService.New()
        product.Eat()
    }
}

==> ./apple/service/service.go <==

package service

import "./apple"

type ProductI interface {
    Eat()
}

type AppleService struct {
}

func (a *AppleService) New() ProductI {
    return &apple.Apple{}
}

==> ./apple/service/apple/apple.go <==

package apple

import "fmt"

type Apple struct {
}

func (a *Apple) Eat() {
    fmt.Println("mniam, mniam")
}

我认为只要声明相同,什么名称或什么导入路径有接口(interface)都没有关系。

最佳答案

我认为你这里有几个问题。首先,您定义了 AppleI 接口(interface)两次,一次在 main 中,一次在 service 中。其次,你似乎在尝试做 Python 或 Java(我猜)风格的包。值得一读 packages

这是编译和运行的代码版本。

==> kamil/main.go

package main

import (
    "kamil/service"
)

type Program struct {
    appleService service.AppleServiceI
}

func main() {
    program := &Program{
        appleService: &service.AppleService{},
    }

    apple := program.appleService.New()
    apple.Eat()
}

==> kamil/service/service.go

package service

import (
    "kamil/service/apple"
)

type AppleServiceI interface {
    New() AppleI
}

type AppleI interface {
    Eat()
}

type AppleService struct {
}

func (a *AppleService) New() AppleI {
    return &apple.Apple{}
}

==> kamil/service/apple/apple.go(未更改)

package apple

import "fmt"

type Apple struct {
}

func (a *Apple) Eat() {
    fmt.Println("mniam, mniam")
}

就是说,我不认为您采用的方法是惯用的 GO,您最终可能会在某个时候撞到头 :)

关于go - 接口(interface)具有相同的方法,但被认为是不同的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21166113/

相关文章:

go - 缓冲 channel 的内存分配如何工作

PHP 和 Golang sha512 不同的结果

reflection - GO 语言 : anonymous structs & Reflection combination

go - 在 Golang 中使用字节数组附加/创建 SVG

go - 转到结构函数和*

arrays - Go 中这两种 "slice copy"方法有什么区别

go - 如何检查一个包直接依赖/间接依赖另一个包?

go - 远程与 logrus 包的 VCS 端点匹配

go - 为什么在Golang中创建 slice 时会有一个CAPACITY参数

html - Golang 模板中的嵌套范围