go - 在 go wiki 中解释 go 接口(interface)定义

标签 go

我了解了一点,并且在一定程度上也了解了界面(比如我如何在 ruby​​ 中进行 ducktyping) 但是阅读接口(interface)定义https://github.com/golang/go/wiki/CodeReviewComments

我不知道要传达什么。

第一:我没看懂评论。

Go interfaces generally belong in the package that uses values of the interface type, not the package that implements those values.

第二:我不明白这个

Do not define interfaces on the implementor side of an API "for mocking"; instead, design the API so that it can be tested using the public API of the real implementation.

第三:我不明白这个例子

Do not define interfaces before they are used: without a realistic example of usage, it is too difficult to see whether an interface is even necessary, let alone what methods it ought to contain.


package consumer  // consumer.go

type Thinger interface { Thing() bool }

func Foo(t Thinger) string { ..... }


package consumer // consumer_test.go

type fakeThinger struct{ … }
func (t fakeThinger) Thing() bool { … }
if Foo(fakeThinger{…}) == "x" { ... }
// DO NOT DO IT!!!
package producer

type Thinger interface { Thing() bool }

type defaultThinger struct{ … }
func (t defaultThinger) Thing() bool { … }

func NewThinger() Thinger { return defaultThinger{ … } }
package producer

type Thinger struct{ … }
func (t Thinger) Thing() bool { … }

func NewThinger() Thinger { return Thinger{ … } }

谁能用通俗易懂的语言解释以上三件事。

最佳答案

暂时忘记与其他语言的类比。将接口(interface)想象成契约(Contract) - 使用它的功能的一组要求。

假设我定义了一个函数 MakeNoise,它需要知道传入的声音,但不关心它。下面的代码全部放在一起,但想象一下这在两个单独的包中——一个用于具体类型,一个用于 MakeNoise。

MakeNoise 函数可以采用特定类型,但这在一定程度上限制了它,可能会使测试更加困难等,因此通常您可能希望它而不是定义它需要该类型做什么 - 在这种情况下它只需要一些带有要调用的 Sound() 方法,除此之外它不关心。

现在在 Cat/Dog 方面,您可能不关心 MakeNoise,甚至还不知道它,您的动物应该单独定义并且不关心它们符合的任何接口(interface)——这些接口(interface)甚至可能还没有被编写.

所以 Wiki 只是说,编写 MakeNoise 的人应该关心它需要什么并将其放在界面中,但是编写 Cat/Dog 的人不应该关心,界面应该与 MakeNoise 一起使用,而不是与 Cat/Dog 一起使用。这意味着以后有人可能会在另一个包中编写 Giraffe,它仍然可以与 MakeNoise 一起使用。

接口(interface)是一个要求,而不是一个 promise 。

https://play.golang.org/p/4r1wiXokKMb

// Here are some types which share one function. 
// They might have other functions too
package main

type Cat struct {}
func (d Cat) Sound() string {
    return "miao"
}

type Dog struct {}
func (d Dog) Sound() string {
    return "woof"
}

func main() {
    cat := Cat{}
    dog := Dog{}

    MakeNoise(cat)
    MakeNoise(dog)
}


// Sounder is the requirement for MakeNoise, so it lives with it.
// perhaps in a package together which knows nothing of cats and dogs.
type Sounder interface {
    Sound() string
}

// MakeNoise prints the sound of the thing
// it only cares the thing makes a Sound
func MakeNoise(thing Sounder) {
    println(thing.Sound())
}

关于go - 在 go wiki 中解释 go 接口(interface)定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57822244/

相关文章:

go - mgo : result has no field or method 错误

go - Go channel 结构中的 `sudog` 是什么意思?

csv - Golang文件读取只读取最后一行

arrays - 在go错误中使用 slice 和数组

sockets - 如何用 Go 读取 FFMPEG?

go - AWS Lambda GoLang 错误

使用缓冲和非缓冲 channel 时遇到麻烦

go - 如何从状态为 101 切换协议(protocol)的响应中读取正文

performance - 为什么我的 GAE 应用程序提供静态文件的延迟如此之高?

Go Fyne 项目无法从 Linux 交叉编译到 Windows