Go 接口实现一个接口

Go 接口实现一个接口,go,Go,在../src/io/io.go中,下面的接口具有写入方法 在../src/net/http/server.go中,接口响应Writer下面实现了Writer接口的写入方法 type ResponseWriter interface { Header() Header Write([]byte) (int, error) WriteHeader(statusCode int) } 从编码风格的角度来看,嵌入到ResponseWriter接口中的Writer接口比实

在../src/io/io.go中,下面的接口具有写入方法

在../src/net/http/server.go中,接口响应Writer下面实现了Writer接口的写入方法

type ResponseWriter interface {

    Header() Header

    Write([]byte) (int, error)

    WriteHeader(statusCode int)
}

从编码风格的角度来看,嵌入到ResponseWriter接口中的Writer接口比实现它更可取吗?

记住,接口本身根本没有实现任何东西。它简单地说,如果您的包使用这些签名实现所有这些函数,那么它可以在需要X接口的地方使用

将其视为一种契约类型:如果我说这里可以使用FooInterface,那么任何完成我所说的FooInterface所做的事情的东西都是可以接受的

按照这里的定义,作者需要以某种方式实现Write。从接口的角度来看,该特定方法的作用并不重要,只是它存在并接受一个字节数组,返回一个int和一个错误。它能做什么取决于一揽子计划的实施

也许它会编程一架无人机来写字节,也许它会侵入时代广场的广告牌并在那里打印信息。重要的是,您至少可以调用Write并返回预期的返回值。副作用不是由接口定义的,而是由包中的实现定义的

具有正确签名的Write函数的存在使包符合Writer接口。它可以有十几种其他的方法;重要的是书写是为了满足要求

ResponseWriter和Writer只有在ResponseWriter说我碰巧要求ResponseWriter实现与Writer相同的接口时才相关——我们都实现Write[]byte int,error;要成为响应编写器,还必须实现Header和WriteHeader。如果Skywriting包也实现了这两个功能,那么它将是一个ResponseWriter

类型ResponseWriter接口不定义Header和WriteHeader的作用,只定义它们必须存在并具有正确的签名。与作家的关系只是我们同意,从概念上来说,回应作家是一个专业作家。定义一个不包含Write的OddResponseWriter接口是完全可能的,尽管这会让人困惑

更专业化的名称意味着具有更专业化名称的接口是具有更简单名称的接口的超集,但Go本身并没有强制实现这一点。正如@colminator所指出的,我们可以通过嵌入更简单的类型来实现这一点;这允许编译器强制执行专用接口也满足非专用接口的约定,并确保如果嵌入式接口的需求发生变化,但嵌入式程序没有改变以满足需求,则代码将无法编译


接口的这种实现为我们提供了很大的灵活性,可以在不重写的情况下用一个包替换另一个包。如果一个函数说请给我一个Writer接口,这样我就可以写出我的结果,如果你换入一个新的包并使用不同的名称,只要你传入的包中有一个匹配的Writer,就不需要再碰这些代码

我想你在谈论这个问题

因此,在上面的示例中,可以像这样重写接口定义:

type ResponseWriter interface {

    Header() Header

    io.Writer // embedded interface type

    WriteHeader(statusCode int)
}
但这是io包的预先安排

http/server.go接口定义可以在不了解io包的情况下存在


通过http/server.go的接口,需要使用与io完全相同的签名进行函数写入。Writer允许许多其他好处,而无需建立到外部io包的正式链接。

这并不特别重要。偏好只是,偏好-个人观点的问题。@Adrian对于通过server.go first的读者来说需要时间,或者可能不知道ResponseWriter实际上是在实现Writer接口的写入方法。嵌入类型将解决这个问题,我不确定这是否相关。他们也不知道它是否实现了我创建的定义WriteHeader的接口。它不是由实现来决定它实现了什么接口,也不是由一个接口来决定它实现了什么其他接口——它不能涵盖所有接口,因为接口都是Go中的duck类型。打包应用程序的优势是什么?宽松地coupled@overexchange浏览页面非常简洁地表达了这一点:确切地说,许多包可以而且非常依赖io.Reader和io.Writer,而没有明确提到包io。许多包实现拨号方法以与其他数据库连接方法保持一致,但不需要正式同意第三方接口定义。但是,如果所有数据库都遵循相同的接口,once可以编写抽象代码,并在不更改客户端代码的情况下从一个数据库切换到另一个数据库。谷歌最近推出了一个界面,用于抽象AWS等现有云服务,这是一个很好的例子 这对我的回答是非常重要的。谢谢
type ResponseWriter interface {

    Header() Header

    io.Writer // embedded interface type

    WriteHeader(statusCode int)
}