当前位置: 首页 > news >正文

golang学习笔记——接口interfaces

文章目录

  • Go 语言接口
  • 例子
  • 空接口
    • 空接口的定义
    • 空接口的应用
      • 空接口作为函数的参数
      • 空接口作为map的值
  • 类型断言
    • 接口值
  • 类型断言例子001
  • 类型断言例子002
  • 类型断言例子003
  • 巩固练习

Go 语言接口

接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节。
interface是一组method的集合,是duck-type programming的一种体现。接口做的事情就像是定义一个协议(规则),只要一台机器有洗衣服和甩干的功能,我就称它为洗衣机。不关心属性(数据),只关心行为(方法)。

为了保护你的Go语言职业生涯,请牢记接口(interface)是一种类型。

interface类型可以定义一组方法,但是不需要实现。并且接口(interface)不能包含任何变量

在这里插入图片描述
实例

/* 定义接口 */
type interface_name interface {method_name1 [return_type]method_name2 [return_type]method_name3 [return_type]...method_namen [return_type]
}/* 定义结构体 */
type struct_name struct {/* variables */
}/* 实现接口方法 */
func (struct_name_variable struct_name) method_name1() [return_type] {/* 方法实现 */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {/* 方法实现*/
}

例子

Go 中的接口是满足隐式实现的(这一点是非常坑人的,建议阅读 Go语言令人厌恶的设计)。 Go 不提供用于实现接口的关键字。

package mainimport ("fmt""math"
)func main() {var s Shape = Square{3}printInformation(s)c := Circle{6}printInformation(c)
}//打印面积和周长
func printInformation(s Shape) {fmt.Printf("%T\n", s)fmt.Println("Area: ", s.Area())fmt.Println("Perimeter:", s.Perimeter())fmt.Println()
}//---Shape 形状---
type Shape interface {//周长Perimeter() float64//面积Area() float64
}//---Square 正方形---
type Square struct {size float64
}func (s Square) Area() float64 {return s.size * s.size
}func (s Square) Perimeter() float64 {return s.size * 4
}//---Circle 圆形---
type Circle struct {radius float64
}func (c Circle) Area() float64 {return math.Pi * c.radius * c.radius
}func (c Circle) Perimeter() float64 {return 2 * math.Pi * c.radius
}

输出

main.Square
Area:  9
Perimeter: 12main.Circle
Area:  113.0973
Perimeter: 37.6991

空接口

空接口的定义

空接口是指没有定义任何方法的接口。因此任何类型都实现了空接口。

空接口类型的变量可以存储任意类型的变量。

func main() {// 定义一个空接口xvar x interface{}s := "pprof.cn"x = sfmt.Printf("type:%T value:%v\n", x, x)i := 100x = ifmt.Printf("type:%T value:%v\n", x, x)b := truex = bfmt.Printf("type:%T value:%v\n", x, x)
}

空接口的应用

空接口作为函数的参数

使用空接口实现可以接收任意类型的函数参数。

// 空接口作为函数参数
func show(a interface{}) {fmt.Printf("type:%T value:%v\n", a, a)
} 

空接口作为map的值

使用空接口实现可以保存任意值的字典。

// 空接口作为map值var studentInfo = make(map[string]interface{})studentInfo["name"] = "李白"studentInfo["age"] = 18studentInfo["married"] = falsefmt.Println(studentInfo) 

类型断言

空接口可以存储任意类型的值,那我们如何获取其存储的具体数据呢?

接口值

一个接口的值(简称接口值)是由一个具体类型和具体类型的值两部分组成的。这两部分分别称为接口的动态类型和动态值。

我们来看一个具体的例子:

var w io.Writer
w = os.Stdout
w = new(bytes.Buffer)
w = nil 

请看下图分解:
在这里插入图片描述
想要判断空接口中的值这个时候就可以使用类型断言,其语法格式:

    x.(T) 

其中:

    x:表示类型为interface{}的变量T:表示断言x可能是的类型。

该语法返回两个参数,第一个参数是x转化为T类型后的变量,第二个值是一个布尔值,若为true则表示断言成功,为false则表示断言失败。

举个例子:

func main() {var x interface{}x = "pprof.cn"v, ok := x.(string)if ok {fmt.Println(v)} else {fmt.Println("类型断言失败")}
} 

上面的示例中如果要断言多次就需要写多个if判断,这个时候我们可以使用switch语句来实现:

func justifyType(x interface{}) {switch v := x.(type) {case string:fmt.Printf("x is a string,value is %v\n", v)case int:fmt.Printf("x is a int is %v\n", v)case bool:fmt.Printf("x is a bool is %v\n", v)default:fmt.Println("unsupport type!")}
} 

因为空接口可以存储任意类型值的特点,所以空接口在Go语言中的使用十分广泛。

关于接口需要注意的是,只有当有两个或两个以上的具体类型必须以相同的方式进行处理时才需要定义接口。不要为了接口而写接口,那样只会增加不必要的抽象,导致不必要的运行时损耗。

类型断言例子001

类型断言也可以判断指针类型

package mainimport "fmt"func main() {var n1 int32 = 30var n2 string = "tomcat"n3 := falsestu1 := Student{}stu2 := &Student{}justifyType(n1,n2,n3,stu1,stu2)
}type Student struct {}func justifyType(items ...interface{}) {for index, x := range items {switch v := x.(type) {case string:fmt.Printf("第%v个参数是 string 类型,值是 %v\n",index,v)case int:fmt.Printf("第%v个参数是 int 类型,值是 %v\n",index,v)case bool:fmt.Printf("第%v个参数是 bool 类型,值是 %v\n",index,v)case Student:fmt.Printf("第%v个参数是 Student 类型,值是 %v\n",index,v)case *Student:fmt.Printf("第%v个参数是 *Student 类型,值是 %v\n",index,v)default:fmt.Println("unsupport type!")}}
} 

类型断言例子002

package mainimport "fmt"func main() {var i interface{} = "Hello, World"str, ok := i.(string)if ok {fmt.Printf("'%s' is a string\n", str)} else {fmt.Println("conversion failed")}
}

类型断言例子003

给Phone结构体一个特有的方法Call(),当Usb接口接收的是Phone变量时,还需要调用call方法

package mainimport "fmt"func main() {//定义一个usb接口数组,可以存放Phone和Camera的结构体变量// 这里就体现出多态数组var usbArr [3]UsbusbArr[0] = Phone{"vivo"}usbArr[1] = Phone{"小米"}usbArr[2] = Camera{"惠普"}//遍历usbArrvar computer Computerfor _, v := range usbArr {computer.Working(v)}
}type Usb interface {Start()Stop()
}type Camera struct {name string		
}type Phone struct {name string
}type Computer struct {name string
}func (c Camera) Start() {fmt.Println("相机开始工作...")
}func (c Camera) Stop() {fmt.Println("相机停止工作...")
}func (p Phone) Start() {fmt.Printf("%s 手机开始工作...\n", p.name )
}func (p Phone) Stop() {fmt.Printf("%s 手机停止工作...\n", p.name )
}func (p Phone) Call() {fmt.Println("手机 打电话")
}func (computer Computer) Working(usb Usb) {usb.Start()if phone, ok := usb.(Phone); ok {phone.Call()}usb.Stop()
}

巩固练习

  1. 在Go语言中,接口是什么?请解释其含义。
  2. 如何定义一个接口?解释接口定义的基本语法。
  3. Go语言中的接口实现是如何工作的?请详细解释。
  4. 什么是空接口?它有什么用途?
  5. 能否给出一些使用接口的例子?这些例子中接口的作用是什么?
  6. Go语言不同接口、声明了同名方法,怎么解决问题?

相关文章:

  • 夺走的第一份工作竟是OpenAI CEO?
  • FPGA设计时序约束八、others类约束之Set_Case_Analysis
  • 坐标系下的运动旋量转换
  • SystemVerilog学习 (7)——面向对象编程
  • PMCW体制雷达系列文章(4) – PMCW雷达之抗干扰
  • transform学习资料
  • 认识Tomcat
  • 【前端开发】JS Vue React中的通用递归函数
  • 机器学习第5天:多项式回归与学习曲线
  • 基于一致性算法的微电网分布式控制MATLAB仿真模型
  • 基于SpringBoot+Vue的新能源汽车充电桩管理系统
  • 数据治理之springboot项目入门
  • windows 安装 Oracle Database 19c
  • 【SpringBoot3+Vue3】二【实战篇】-后端
  • 系列五、怎么查看默认的垃圾收集器是哪个?
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • 【附node操作实例】redis简明入门系列—字符串类型
  • 30秒的PHP代码片段(1)数组 - Array
  • create-react-app项目添加less配置
  • iOS小技巧之UIImagePickerController实现头像选择
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • SpiderData 2019年2月13日 DApp数据排行榜
  • SQLServer之创建数据库快照
  • 从零开始在ubuntu上搭建node开发环境
  • 大快搜索数据爬虫技术实例安装教学篇
  • 分享一份非常强势的Android面试题
  • 前端临床手札——文件上传
  • 使用putty远程连接linux
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 学习HTTP相关知识笔记
  • 用Python写一份独特的元宵节祝福
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • #微信小程序:微信小程序常见的配置传旨
  • (1)常见O(n^2)排序算法解析
  • (16)UiBot:智能化软件机器人(以头歌抓取课程数据为例)
  • (C++17) std算法之执行策略 execution
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (七)Java对象在Hibernate持久化层的状态
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (五)大数据实战——使用模板虚拟机实现hadoop集群虚拟机克隆及网络相关配置
  • (转)http协议
  • (转)微软牛津计划介绍——屌爆了的自然数据处理解决方案(人脸/语音识别,计算机视觉与语言理解)...
  • (转载)(官方)UE4--图像编程----着色器开发
  • .axf 转化 .bin文件 的方法
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .Net Winform开发笔记(一)
  • .NET中的Exception处理(C#)
  • @ModelAttribute 注解
  • @Resource和@Autowired的区别
  • [ C++ ] STL_stack(栈)queue(队列)使用及其重要接口模拟实现
  • [ C++ ] STL---仿函数与priority_queue
  • [C#]winform制作仪表盘好用的表盘控件和使用方法