Go语言中接口的使用

幸运草 2020年4月22日22:10:14函数代码评论阅读模式

1 概述

接口,interface,是用于规范对象应该具备哪些方法的技术。OOP中与结构体配合使用,对象使用结构体规范应该具有的书写,而对外通过接口暴露方法。Go 语言的接口设计是非侵入式的,接口实现者(也就是结构体)无须指明实现哪一个接口。编译器在编译时来确定使用哪个接口。
在 Go 语言中,接口是一种引用的数据类型出现的。但体现的功能是规范,而不是数据。
做 OOP 开发时,通常要保证一类操作具有相同的方法调用,此时就需要使用接口实现。

2 定义语法

type 接口名 interface {
  接口中定义的规范方法列表
}

演示为:

// 定义接口
type Logger interface {
  // 写入一个日志事件
  write(line string) int
  // 获取日志
  fetch() string
}

我们定义了一个 Logger 接口。其中定义了两个函数:write, fetch。

3 对象实现接口

依据接口定义,为对象定义相应方法,即为实现接口。接口设计是非侵入式的,因此不需要显式的在结构体上进行定义。

// 文件日志操作类(结构体)
type FileLogger struct {
}
// 实现 Logger接口
func (fl *FileLogger) write(line string) int {  
  // 功能不表
  return 0
}
func (fl *FileLogger) fetch() string {
  // 功能不表
  return ""
}

对象实现接口时,有以下几个特点:

  • 一个类型对象可以实现多个接口,只需要将全部接口中定义的方法实现即可。注意接口间相互独立的,没有关联。
  • 一个接口可以同时被多个类型对象实现。
  • 一个接口的方法,可以通过内嵌结构体的方式来实现,不要求由一个结构体完全实现。

4 判断对象是否实现接口

我们通过将结构体对象赋值给接口对象的方式,来检测对象是否满足某个接口,演示为:

// 对象
fl := &FileLogger{}
// 声明一个Logger类型接口
var log Logger
// 将需要检测的对象,赋值给接口对象
// 如果可以赋值成功,说明满足接口限定,否则不满足
log = fl
// 用一下接口,否则会报告变量定义未使用的错误
fmt.Println(log)

以上代码,若 fl 对象满足接口 log 的定义,赋值会成功。若没有满足,赋值失败,提示未实现接口的提示,提示类似于:

cannot use fl (type *FileLogger) as type Logger in assignment:
*fl does not implement Logger (missing wirte method)

同理,若函数的参数为接口类型,在调用函数时,传递的参数不满足接口,也会触发如上的错误:

// 参数 logger 为接口 Logger类型
func writeLog(logger Logger, line string) int {
  fmt.Println("Logger Run")  
  // 实现略
  return 0

}
// 调用函数
// 对象
fl := &FileLogger{}
writeLog(fl, "some log")

以上代码,若 fl 对象未满足接口 Logger 的定义,函数调用失败。提示类似的 does not implement 错误。

5 通过接口调用对象方法

当将对象赋值给接口后,检测通过,赋值成功。就可以使用接口调用对象方法了,此时对象方法接收器接收的对象还是原对象。直接赋值 和 函数调用赋值 都一样。

// 对象赋值给接口
log = fl
// 调用对象方法
log.write("log line")
// 函数参数也是如此
func writeLog(logger Logger, line string) int {  
  // 调用对象方法
  logger.write(line)
  return 0
 }

6 空接口

空接口,没有定义任何成员的接口。
语法演示:

type any interface {
}

由于没有定义任何的函数,意味着全部的对象都满足该接口。这个范围要扩大到全部数据类型上。不仅仅是对象。主要作用是类型通配,通常在定义函数时,表示函数可以接收任何类型的参数,例如 fmt.Print。

定义函数接收空接口类型参数时,可以使用 switch v.(type) 接口检测类型,这个结构称之为类型分支:

func sayType(v interface{}) {
  switch v.(type) {
  case bool:
    fmt.Println("bool")
  case float64:
    fmt.Println("float64")
  case string:
    fmt.Println("string")
  default:
    fmt.Println("其他类型")
  }
}

7 接口间的嵌套

接口类似于接头体,可以嵌套,达到接口重用的目的。以系统 io 包定义的接口为例:

type Writer interface {
    Write(p []byte) (n int, err error)
}
type Closer interface {
    Close() error
}
// WriteCloser 接口
type WriteCloser interface {  
  // 内嵌了 Write,Closer 接口
  Writer
  Closer
}

此时,若想实现 WriteCloser 接口,则 Writer 与 Closer 接口中定义的而方法需要全部实现。

完!
全部文章整理在:Go语言指导|小韩说课
原文出自:小韩说课

特别声明:以上文章内容仅代表作者本人观点,不代表变化吧观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与变化吧联系。

  • 赞助本站
  • 微信扫一扫
  • weinxin
  • 加入Q群
  • QQ扫一扫
  • weinxin
幸运草
Go语言中的常量 函数代码

Go语言中的常量

1 概述 常量,一经定义不可更改的量。功能角度看,当出现不需要被更改的数据时,应该使用常量进行存储,例如圆周率。从语法的角度看,使用常量可以保证数据,在整个运行期间内,不会被更改。例如当前处理器的架构...
Go语言的接口 函数代码

Go语言的接口

Go语言-接口 在Go语言中,一个接口类型总是代表着某一种类型(即所有实现它的类型)的行为。一个接口类型的声明通常会包含关键字type、类型名称、关键字interface以及由花括号包裹的若干方法声明...
Go语言支持的正则语法 函数代码

Go语言支持的正则语法

1 字符 语法 说明 . 任意字符,在单行模式(s标志)下,也可以匹配换行 字符类 否定字符类 d Perl 字符类 D 否定 Perl 字符类 ASCII 字符类 否定 ASCII 字符类 pN U...
Go语言的包管理 函数代码

Go语言的包管理

1 概述 Go 语言的源码复用建立在包(package)基础之上。包通过 package, import, GOPATH 操作完成。 2 main包 Go 语言的入口 main() 函数所在的包(pa...

发表评论