Golang 语言怎么使用接口编程?

简介: Golang 语言怎么使用接口编程?

介绍

关于 Golang 语言接口的使用,在之前的一篇公众号文章中已经介绍过,未阅读的读者朋友,如果感兴趣,可以按需翻阅文末推荐阅读列表。本文我们主要介绍在 Golang 语言中,如何使用接口编程?以及接口的使用技巧。

接口编程

在 Golang 应用开发中,除了使用 Func,我们还经常会用到 Method,比如:

示例代码:

type Cat struct {
 name string
}
func (c Cat) Eat() {
 fmt.Printf("%s 正在吃饭\n", c.name)
}
func main () {
 c := Cat{name: "kitty"}
 c.Eat()
}

阅读上面这段代码,我们定义了一个 Cat 结构体,然后实现 Eat 方法。在 Golang 语言中,使用 Method 和使用 Func 的区别是,使用 Method 可以将类型和方法封装在一起,实现强耦合。

但是,如果我们除了 Cat 之外,现在又新增了 Dog,也要实现 Eat 方法。我们除了也定义一个 Dog 结构体,然后实现 Eat 方法之外。还可以定义一个 Animal 接口,实现多态。

示例代码:

type Animal interface {
 Eat()
}
type Cat struct {
 name string
}
type Dog struct {
 name string
}
func (c Cat) Eat() {
 fmt.Printf("%s 正在吃饭\n", c.name)
}
func (c Cat) Sleep() {
 fmt.Printf("%s 正在睡觉\n", c.name)
}
func (d Dog) Eat() {
 fmt.Printf("%s 正在吃饭\n", d.name)
}
func main () {
 var a Animal
 c := Cat{name: "kitty"}
 d := Dog{name: "101"}
 a = c
 a.Eat()
 a = d
 a.Eat()
}

阅读上面这段代码,我们定义了一个包含 Eat() 方法的接口 Animal,Cat 和 Dog 分别实现 Animal 接口的 Eat() 方法,然后就可以通过将 Cat 类型和 Dog 类型的变量赋值给 Animal 接口,实现多态。

除此之外,我们还可以对上面这段代码进一步优化,上面这段代码虽然实现了多态,但是实现上有些繁琐。我们可以声明一个接收 Animal 接口类型参数的函数 AnimalAction()

示例代码:

type Animal interface {
 Action() string
}
type Cat struct {
 name string
}
type Dog struct {
 name string
}
func (c Cat) Action() string {
 return fmt.Sprintf("Cat %s 正在吃饭", c.name)
}
func (d Dog) Action() string {
 return fmt.Sprintf("Dog %s 正在吃饭", d.name)
}
func AnimalAction (a Animal) {
 fmt.Println(a.Action())
}
func main () {
 c := Cat{name: "Kitty"}
 AnimalAction(c)
 d := Dog{name: "101"}
 AnimalAction(d)
}

阅读上面这段代码,是否感觉似曾相识。在 Golang 语言标准库中有很多这种用法。

03

接口使用技巧

  • 尽量定义包含方法少的接口,建议控制接口方法数量不超过 3 个
    我们可以在一些 Golang 语言标准库中发现,很多接口包含的方法数量都不超过 3 个,也有很多接口仅包含 1 个方法。
    控制接口包含方法的数量尽量少的好处是接口包含的方法越少,越容易实现和组合。
  • 如何强制实现接口的所有方法
    Golang 语言中的接口是隐式实现的,并且不强制实现接口的所有方法。如果我们需要强制实现接口的所有方法,做法如下:
    示例代码:
type Animal interface {
  Eat()
  Sleep()
}
type Cat struct {}
func (c Cat) Eat() {
  fmt.Println("Cat 正在吃饭")
}
// func (c Cat) Sleep() {
//  fmt.Println("Cat 正在睡觉")
// }
type Dog struct {}
func (d Dog) Eat() {
  fmt.Println("Dog 正在吃饭")
}
// func (d Dog) Sleep() {
//  fmt.Println("Dog 正在睡觉")
// }
func main () {
  var _ Animal = (*Cat)(nil)
  var _ Animal = (*Dog)(nil)
  c := Cat{}
  c.Eat()
  d := Dog{}
  d.Eat()
}
  • OutPut:
cannot use (*Cat)(nil) (type *Cat) as type Animal in assignment:
  *Cat does not implement Animal (missing Sleep method)
cannot use (*Dog)(nil) (type *Dog) as type Animal in assignment:
  *Dog does not implement Animal (missing Sleep method)
  • 阅读上面这段代码,我们通过声明变量:
var _ Animal = (*Cat)(nil)
var _ Animal = (*Dog)(nil)
  • 强制实现接口的所有方法。
  • 尽量不使用空接口类型作为函数参数
    Golang 语言是强类型静态语言,Golang 编译器在编译期间会对变量做类型检查。如果函数或方法接收的参数类型是空接口 interface{},编译器将收不到任何信息,也就不会对空接口类型的变量进行类型检查,接收参数的类型将需要开发者自己做类型检查。所以开发者尽量不要使用空接口 interface{} 变量作为接收参数。
    但是空接口 interface{} 类型也并非完全无用武之地,因为目前 Golang 语言(v1.16.4)还未支持泛型,当需要处理未知类型的参数时,可以使用空接口 interface{} 类型,在 Golang 语言标准库中也有该使用方式,比如 fmt 包。

04

总结

本文我们介绍了如何使用接口编程,通过一个简单示例,循序渐进地介绍了接口编程的使用方式,此外,我们还介绍了一些接口使用技巧。

建议读者朋友们动手敲一下示例代码,通过亲自运行代码加深理解。关于接口本身的介绍,读者朋友们可以按需阅读推荐列表中的相关文章。

推荐阅读:

保持 Modules 的兼容性

参考资料:

https://golang.org/doc/effective_go#interfaces_and_types


目录
相关文章
|
2月前
|
Go
Golang语言之管道channel快速入门篇
这篇文章是关于Go语言中管道(channel)的快速入门教程,涵盖了管道的基本使用、有缓冲和无缓冲管道的区别、管道的关闭、遍历、协程和管道的协同工作、单向通道的使用以及select多路复用的详细案例和解释。
111 4
Golang语言之管道channel快速入门篇
|
2月前
|
Go
Golang语言文件操作快速入门篇
这篇文章是关于Go语言文件操作快速入门的教程,涵盖了文件的读取、写入、复制操作以及使用标准库中的ioutil、bufio、os等包进行文件操作的详细案例。
66 4
Golang语言文件操作快速入门篇
|
2月前
|
Go
Golang语言之gRPC程序设计示例
这篇文章是关于Golang语言使用gRPC进行程序设计的详细教程,涵盖了RPC协议的介绍、gRPC环境的搭建、Protocol Buffers的使用、gRPC服务的编写和通信示例。
101 3
Golang语言之gRPC程序设计示例
|
2月前
|
安全 Go
Golang语言goroutine协程并发安全及锁机制
这篇文章是关于Go语言中多协程操作同一数据问题、互斥锁Mutex和读写互斥锁RWMutex的详细介绍及使用案例,涵盖了如何使用这些同步原语来解决并发访问共享资源时的数据安全问题。
86 4
|
16天前
|
Unix Linux Go
go进阶编程:Golang中的文件与文件夹操作指南
本文详细介绍了Golang中文件与文件夹的基本操作,包括读取、写入、创建、删除和遍历等。通过示例代码展示了如何使用`os`和`io/ioutil`包进行文件操作,并强调了错误处理、权限控制和路径问题的重要性。适合初学者和有经验的开发者参考。
|
2月前
|
Go 调度
Golang语言goroutine协程篇
这篇文章是关于Go语言goroutine协程的详细教程,涵盖了并发编程的常见术语、goroutine的创建和调度、使用sync.WaitGroup控制协程退出以及如何通过GOMAXPROCS设置程序并发时占用的CPU逻辑核心数。
50 4
Golang语言goroutine协程篇
|
2月前
|
Prometheus Cloud Native Go
Golang语言之Prometheus的日志模块使用案例
这篇文章是关于如何在Golang语言项目中使用Prometheus的日志模块的案例,包括源代码编写、编译和测试步骤。
53 3
Golang语言之Prometheus的日志模块使用案例
|
1月前
|
前端开发 中间件 Go
实践Golang语言N层应用架构
【10月更文挑战第2天】本文介绍了如何在Go语言中使用Gin框架实现N层体系结构,借鉴了J2EE平台的多层分布式应用程序模型。文章首先概述了N层体系结构的基本概念,接着详细列出了Go语言中对应的构件名称,包括前端框架(如Vue.js、React)、Gin的处理函数和中间件、依赖注入和配置管理、会话管理和ORM库(如gorm或ent)。最后,提供了具体的代码示例,展示了如何实现HTTP请求处理、会话管理和数据库操作。
31 0
|
2月前
|
Go
Golang语言错误处理机制
这篇文章是关于Golang语言错误处理机制的教程,介绍了使用defer结合recover捕获错误、基于errors.New自定义错误以及使用panic抛出自定义错误的方法。
46 3
|
2月前
|
Go
Golang语言之函数(func)进阶篇
这篇文章是关于Golang语言中函数高级用法的教程,涵盖了初始化函数、匿名函数、闭包函数、高阶函数、defer关键字以及系统函数的使用和案例。
59 3
Golang语言之函数(func)进阶篇