一文带你了解Go语言中接口的使用
作者:陈明勇 发布时间:2024-02-20 04:01:34
接口
在 Go
语言中,接口是一种抽象的类型,是一组方法的集合。接口存在的目的是定义规范,而规范的细节由其他对象去实现。我们来看一个例子:
import "fmt"
type Person struct {
Name string
}
func main() {
person := Person{Name: "cmy"}
fmt.Println(person) // {cmy}
}
上述代码定义了结构体 Person
,main
函数创建了此结构体的变量 person
,然后通过 fmt
包里的 Println
函数打印这个结构体,打印结果为 {cmy}
。在此基础上,我们改造一下代码:
import "fmt"
type Person struct {
Name string
}
func (p Person) String() string {
return fmt.Sprintf("name: %s", p.Name)
}
func main() {
person := Person{Name: "cmy"}
fmt.Println(person) // name: cmy
}
新改造的代码里为结构体 Person
添加一个结构体方法 String() string
,方法的返回结果是对 name
进行格式化,我们再打印一下结构体,观察结果发现是 String()
方法返回的值,而不是 {cmy}
。 为什么是这样呢?这是因为 fmt.Println(T)
函数的实现细节里,会对结构体进行判断,如果结构体实现了 Stringer
接口,则会直接打印 String()
方法的返回值。以下是 Stringer 接口的代码:
type Stringer interface {
String() string
}
结构体实现了这个接口,也就意味着遵守这个接口所定义的规范,fmt.Println(T)
函数发现结构体有这个规范,因此就会根据规范来打印信息。基于 Stringer
接口,我们来看看接口的语法格式:
type XXX interface {
// methods
}
1、type
接口的声明,必须以 type
关键字开头。
2、接口名
推荐驼峰式命名法,首字母大写的方法名可以在包外访问,小写的只能在包内访问。
3、interface
接口的标识。
4、接口体
大括号里面声明规范,也就是声明方法,方法必须具有名字。
接口的实现
在 Go
语言里,接口的实现不是基于接口,而是基于方法。如果一个自定义类型拥有了某个接口的所有方法,那么这个自定义类型就实现这个接口。接口的实现在上述的例子中有所体现,Person
结构体定义了 String() string
方法,拥有了 Stringer
接口的所有方法,因此实现了 Stringer
接口。
一个自定义类型可以实现多个接口
type A interface {
a()
}
type B interface {
b()
}
type Person struct {
Name string
}
func (p Person) a() {
}
func (p Person) b() {
}
A
接口声明了 a
方法, B
接口声明了 b
方法,Person
结构体定义了 a
和 b
两个方法,因此 Person
结构体实现了 A
和 B
两个接口。
接口类型变量
一旦接口被定义,它就可以用于声明变量。
import "fmt"
type A interface {
}
func main() {
var a A
fmt.Println(a) // <nil>
}
如果只声明接口变量,不初始化,变量的值默认为 nil
,因为接口类型实际上是一个指针。若为接口赋初值,需要选择一个合法的值,即被赋值的基类必须实现这个接口。
空接口
在 Go
语言里面可以认为所有类型实现了空接口,因为空接口没有任何的方法。
import "fmt"
type EmptyInterface interface {
}
func main() {
var a EmptyInterface = 1
var b EmptyInterface = true
var c EmptyInterface = "hello"
var d EmptyInterface = 3.14
var e EmptyInterface = 'c'
fmt.Println(a, b, c, d, e) // 1 true hello 3.14 99
}
所有类型都实现空接口,因此空接口变量可以被赋初值为任意类型的值或变量。
类型断言
Go
语言支持类型断言操作,通过这个操作,可以还原接口变量的右值(被赋的初值)。类型断言的语法形式通常为:
v, ok := a.(T)
如果断言成功,那么 v
的值为接口变量的值,ok
的值为 true
;如果断言失败,v
的值为 T
类型的零值,ok
的值为 false
。
类型断言变种 type switch
通过 type switch
的方式,可以判断接口变量属于哪种动态类型。
import "fmt"
type EmptyInterface interface {
}
func main() {
var a EmptyInterface = 1
switch a.(type) {
case string:
fmt.Println("a 的右值类型为 string")
case int:
fmt.Println("a 的右值类型为 int")
case bool:
fmt.Println("a 的右值类型为 bool")
case float64:
fmt.Println("a 的右值类型为 float64")
}
}
小结
本文先是对接口的定义进行介绍,然后通过一个例子,了解了接口其中的一个应用场景和引出接口的语法格式以及实现的方法,然后介绍了空接口的特点和类型断言,最后介绍了变种的类型断言 type switch
的应用例子。
来源:https://juejin.cn/post/7172579057899405326
猜你喜欢
- 大家好,今天给大家分享一下明哥整理的一篇 Python 参数的内容,内容非常的干,全文通过案例的形式来理解知识点,自认为比网上 80% 的文
- 1、上下文概念上下文,说白了就是所谓的语境,就是语言环境。比如单独拎出来一篇文章的某一句话,我们可能不能理解它的意思,但是通过这句话所处的语
- 前言python 打开浏览器,可以做简单的刷网页的小程序 and 其他有想象力的程序。不过仅供学习,勿用非法用途。python的webbro
- lxmllxml 是 Python 的一个库,用于解析和呈现 XML 和 HTML。它支持多种内置和第三方 XML 和 HTML 标记,例如
- 前言正则表达式是文本处理领域中的一个强大的工具,它可以让文本处理的能力呈指数级的提升,如果一款文本编辑器不支持正则表达式,那么它就算不上是一
- 本文实例为大家分享了Python3实现汉语转换为汉语拼音的具体代码,供大家参考,具体内容如下工具: Python3.6.2,pycharm1
- 下拉框连动JavaScript代码,市区二级联动多级联动下拉选择框,动态获取下一级琥珀无限级联动菜单-JavaScript版 <htm
- 在北美,人们对于 PostgreSQL 的热情不断升温。随着 PostgreSQL 的发展, PostgreSQL 8.x 已经从技术上超越
- 如果我们数据库的ID设置为varchar型的 在查询的时候order by id的话我们是不希望看到如下情况的。我们可以把varchar转换
- //有1-22个文件夹,各文件夹下有Detect_0文件夹,此文件夹下有source与mask文件夹,目的是将需要获取图片的文件夹下的图片复
- 将视图与缓存系统进行了耦合,从几个方面来说并不理想。 例如,你可能想在某个无缓存的站点中重用该视图函数,或者你可能想将该视图发布给那些不想通
- 前言项目中一般分测试环境(QAS),生产环境(PRD),当我们的项目经历了一次周期跨度较长的更新后,当我们发布到生产环境时,首要的任务是将新
- 1 图1第一个图是蚊香,感兴趣的小伙伴可以自己尝试在python中用turtle库绘制一下。具体代码如下:#画蚊香import turtle
- 一、概述1、描述变量类型注解是用来对变量和函数的参数返回值类型做注解,让调用方减少类型方面的错误,也可以提高代码的可读性和易用性。但是,变量
- 本文实例讲述了Python实现的桶排序算法。分享给大家供大家参考,具体如下:桶排序也叫计数排序,简单来说,就是将数据集里面所有元素按顺序列举
- 前些天用python处理xml的转换的一个小程序,用来把xml,xsl转换成html。用的libxml2,所以还要先安装了libxml2模块
- 假设我们要添加一个我们自己的Middleware,用来记录每次请求的日志下面就是一个符合规范的Middleware, 构造函数中接受一个WS
- 如下图所示的文件,我们按文件名后缀对文件进行分类使用os和shutil首先导入对应的模块,将目标文件夹和到分类到的文件夹定义import o
- 目录假想场景基本思路pywinauto方案win32gui方案更一般的方案利用Python进行Excel自动化操作的过程中,尤其是涉及VBA
- UPDATE是否会加锁?SQL语句为如下时,是否会加锁?UPDATE table1 SET num = num + 1 WHERE id=1