为什么在Golang中需要接口?

为什么在Golang中需要接口?,第1张

为什么在Golang中需要接口

接口太大了,不能在这里给出全面的答案,但是有些事情需要弄清楚它们的用途。

接口是一种 工具
。是否使用它们取决于您自己,但是它们可以使代码更清晰,更短,更易读,并且它们可以在程序包,客户端(用户)和服务器(提供者)之间提供良好的API。

是的,您可以创建自己的

struct
类型,并且可以“附加”方法,例如:

type Cat struct{}func (c Cat) Say() string { return "meow" }type Dog struct{}func (d Dog) Say() string { return "woof" }func main() {    c := Cat{}    fmt.Println("Cat says:", c.Say())    d := Dog{}    fmt.Println("Dog says:", d.Say())}

我们已经在上面的代码中看到了一些重复:在使两者

Cat
同时
Dog
说话时。我们可以像 对待动物
一样对待两者吗?并不是的。当然,我们可以将两者都作为处理
interface{}
,但是如果这样做,则不能调用它们的
Say()
方法,因为type的值
interface{}
未定义任何方法。

上面的两种类型都有一些 相似之处 :两者都具有

Say()
签名相同的方法(参数和结果类型)。我们可以通过一个接口 捕获 它:

type Sayer interface {    Say() string}

接口仅包含方法的 签名 ,而不包含方法的 实现

请注意,在Go语言中,如果类型的方法集是该接口的超集,则该类型 隐式
实现该接口。没有意图的声明。这是什么意思?我们以前

Cat
Dog
类型已经实现了这个
Sayer
接口,即使在我们前面写了他们这个接口定义根本不存在,而我们没有接触他们,以纪念他们什么。他们只是做。

接口指定行为 。实现接口的类型意味着该类型具有接口“规定”的所有方法。

由于两者都实现了

Sayer
,我们可以将两者都当作的值来处理
Sayer
,因此它们具有相同的地方。看看我们如何统一处理这两个问题:

animals := []Sayer{c, d}for _, a := range animals {    fmt.Println(reflect.TypeOf(a).Name(), "says:", a.Say())}

(这反映出部分只是为了获得类型名称,到目前为止还不多。)

最重要的部分是,我们可以同时处理

Cat
Dog
视为同类(接口类型),并与他们合作/使用它们。如果您很快要使用
Say()
方法创建其他类型,则可以在
Cat
和旁边排队
Dog

type Horse struct{}func (h Horse) Say() string { return "neigh" }animals = append(animals, Horse{})for _, a := range animals {    fmt.Println(reflect.TypeOf(a).Name(), "says:", a.Say())}

假设您要编写其他适用于这些类型的代码。辅助功能:

func MakeCatTalk(c Cat) {    fmt.Println("Cat says:", c.Say())}

是的,上面的函数可以使用

Cat
,也可以不使用。如果您想要类似的东西,则必须为每种类型编写它。不用说这有多糟。

是的,您可以编写它来接受的参数

interface{}
,并使用类型断言或类型开关,这将减少辅助函数的数量,但看起来仍然很丑陋。

解决方案?是的,界面。只需声明该函数以采用接口类型的值即可,该接口类型定义了您要对其执行的 *** 作,仅此而已:

func MakeTalk(s Sayer) {    fmt.Println(reflect.TypeOf(s).Name(), "says:", s.Say())}

你可以调用这个函数的值

Cat
Dog
Horse
或任何其他类型的现在不知道,直到,有一个
Say()
方法。凉。

在Go Playground上尝试这些示例。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5462882.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-12
下一篇 2022-12-12

发表评论

登录后才能评论

评论列表(0条)

保存