接口的声明使用 | 豆包MarsCode AI刷题

34 阅读3分钟

接口

golang中的接口设计非常出色,因为它解耦了接口和实现类之间的联系,使得进一步增加了我们编码的灵活度,解决了供需关系颠倒的问题。但是世上没有绝对的好坏,golang中的接口在方便了我们编码的同时也带来了一些问题,比如说由于没了接口和实现类的强绑定,其实也一定程度上增加了开发和维护的成本。

总体来说这是一个仁者见仁的改动,有些写惯了Java的同学可能会觉得没有必要,这是过度解绑,有些人之前深受其害的同学可能觉得这个进步非常关键。但不论你怎么看,这都不影响我们学习它,毕竟学习本身是不带立场的

接口本身就是一种规范,能让大家在一个框架下开发,比如张三新进入部门,开发一个新的支付功能,在接口的限制下,开发就会会规范很多。就像USB接口一样,定义统一接口,无论外部实现的是音响还是硬盘,必须都按定义好的数据格式开发。

Go的接口语法

基本语法

在 Golang 中,interface 是一组 method 的集合,是 duck-type programming 的一种体现。不关心属性(数据),只关心行为(方法)。具体使用中你可以自定义自己的 struct,并提供特定的 interface 里面的 method 就可以把它当成 interface 来使用。

每个接口由数个方法组成,接口的定义格式如下:

 type 接口类型名 interface{
     方法名1( 参数列表1 ) 返回值列表1
     方法名2( 参数列表2 ) 返回值列表2
     …
 }

其中:

  • 接口名:使用type将接口定义为自定义的类型名。Go语言的接口在命名时,一般会在单词后面添加er,如有写操作的接口叫Writer,有字符串功能的接口叫Stringer等。接口名最好要能突出该接口的类型含义。
  • 方法名:当方法名首字母是大写且这个接口类型名首字母也是大写时,这个方法可以被接口所在的包(package)之外的代码访问。
  • 参数列表、返回值列表:参数列表和返回值列表中的参数变量名可以省略。

实现接口的条件

一个对象只要全部实现了接口中的方法,那么就实现了这个接口。换句话说,接口就是一个需要实现的方法列表

我们来定义一个Animal接口:

 // Animal 接口
 type Animal interface {
     sleep()
 }

定义DogCat两个结构体:

 type Dog struct {
     name string
 }
 type Cat struct {
     name string
 }

因为Animal接口里只有一个sleep方法,所以我们只需要给DogCat类分别实现sleep方法就可以实现Sayer接口了。

 // Dog实现了Animal接口
 func (d Dog) sleep() {
     fmt.Printf("%s正在侧卧着睡觉\n", d.name)
 }
 // Cat实现了Animal接口
 func (c Cat) sleep() {
     fmt.Printf("%s正在卷成团睡觉\n", c.name)
 }

接口的实现就是这么简单,只要实现了接口中的所有方法,就实现了这个接口。

接口类型变量

那实现了接口有什么用呢?

接口类型变量能够存储所有实现了该接口的实例。 例如上面的示例中,Animal类型的变量能够存储DogCat类型的变量。

 ​
 func foo(animal Animal)  {
     animal.sleep()
 }
 ​
 func main() {
     var a Animal
 ​
     var d = Dog{"川普"}
     var c = Cat{"拜登"}
 ​
     // 案例1
     a = d
     a.sleep()
     a = c
     a.sleep()
     // 案例2
     foo(d)
     foo(c)
 }