12.Go语言干货-接口类型

12.Go语言干货-接口类型,第1张

概述1.前言永远不要高估自己接口(interface)是一种类型!!2.接口类型1.接口是一种类型,使用关键字type与interface进行定义2.接口类型只定义方法,不关心数据3.通俗地讲接口类型定义了规则,不关心规则的实现3.接口类型的定义接口的定义格式type接口类型名interface{ 方法名1 1.前言

永远不要高估自己
接口(interface)是一种类型!!

2.接口类型

1.接口是一种类型,使用关键字typeinterface进行定义
2.接口类型只定义方法,不关心数据
3.通俗地讲接口类型定义了规则,不关心规则的实现

3.接口类型的定义

接口的定义格式

type 接口类型名 interface {	方法名1(参数列表1) 返回值列表1	方法名2(参数列表2) 返回值列表2	...}
接口类型名:从type关键字可以看出接口就是类型的一种,接口类型名称就是给接口去哟个名字。接口类型命名规则一般会在单词的后面添加 er,比如说写 *** 作的接口名称名义为 Writer,字符串接口叫做 Stringer,接口类型的名称最好能体现接口的含义!方法名:当方法名称首字母大写并且接口类型名称首字母也是大写,这个方法可以被接口所在包之外的代码使用参数列表、返回值列表:可以省略

举个栗子:

type Writer interface(	Write([]byte) error)

所见即所得,看见接口类型名称与方法名称大概能猜出,这个接口的功能!

4.实现接口的条件

接口类型就是一个需要实现的方法列表,一个结构体示例实现了接口中的所有方法,那么就实现了这个接口类型

1.我们定义一个Caller接口:

// Caller 接口类型type Caller interface {	call()}

2.定义DogCat 两个结构体:

type Dog struct{}type Cat struct{}

3.因为Caller接口里面有一个call方法,所以我们需要给DogCat两个结构体分别实现Call方法

// Dog 实现了Caller接口类型func (d Dog) call(){	fmt.Println("汪汪汪...")}// Cat 实现了Caller接口类型func (c Cat) call(){	fmt.Println("喵喵喵...")}

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

5.接口类型变量

接口类型变量能够存储所有实现了该接口的实例。
列如上面的例子中,DogCat的实例实现了,接口Caller中的call方法,那么定义一个Caller类型的变量就可以存储Dog与Cat的实例。

func main(){	var x Caller // 声明一个Caller类型的变量x	c := Cat{} // 实例化Cat	d := Dog{} // 实例化Dog	x = c // 可以吧cat的实例赋值给x	x.call() // 喵喵喵	x = d // 可以吧dog的实例赋值给x	x.call() // 汪汪汪}

观察下列代码,感受_的妙用

// 摘自gin框架routergroup.gotype IRouter interface{ ... }type RouterGroup struct { ... }var _ IRouter = &RouterGroup{}  // 确保RouterGroup实现了接口IRouter
6.值接受者与指针接受者实现接口的区别

定义一个Mover接口类型与一个dog结构体

type Mover interface {	move()}type cat struct{}
6.1 值类型接受者实现接口
func (c cat) move(){	fmt.Println("猫动起来了")}

此时实现接口类型的是cat类型

func main(){	var x Mover	var Tom = cat{} //Tom是cat类型	x = Tom // x可以接受cat类型	var jialaolian = &cat{} // jiaolaolian是*cat类型	x = jialaolian // x 可以接受*cat类型	x.move()}

从代码可以看出,使用值接受者实现接口之后,不管是cat结构体还是结构体指针*cat类型的变量都可以赋值给该接口变量

6.2 指针接受者实现接口

同样的代码我们再来测试一下使用指针接受者有什么区别

func (c *cat) move(){	fmt.Println("猫动起来了")}func main(){	var x Mover	var Tom = cat{} // Tom是cat类型	x = Tom // x接收cat类型报错	var jialaolian = &cat{}	x = jialaolian // x可以接受*cat类型}

此时实现Mover接口类型是*cat类型,所以不能给x传入cat类型的Tom,此时x只能传入*cat类型的值

7.结构体类型与接口类型的关系7.1 一个结构体类型实现多个接口类型

一个结构体类型可以同时实现多个接口类型,并且接口类型之间互相独立。

举个栗子:猫可以叫,也可以动,我们可以分别定义CallerMover接口

type Caller interface{	call()}type Mover interface {	move()}

cat 即实现了Caller接口,也实现了Mover接口

type cat struct {	name string}func (c cat) call() {	fmt.Println("喵喵喵")}func (c cat)move() {	fmt.println("动起来")}func main(){	var x Caller	var y Mover	var c1 = cat(name:Tom)	x = c1	y = c1	x.call()	x.move()}
7.2 多个结构体类型实现同一接口类型

。。。

8 接口类型嵌套

接口与接口之前可以通过嵌套创造出新的接口

// Caller 接口type Caller interface {	call()}// Mover 接口type Mover interface {	move()}//接口嵌套type Animal interface {	Caller	Mover}

嵌套得到的接口使用与普通接口一样

type cat struct {	name string}func (c cat) call(){	fmt.Println("喵喵喵")}func (c cat)move(){	fmt.Println("动起来")}func main(){	var x Animal	x = cat{name:"Tom"}	x.move()	x.call()}
9 空接口9.1 空接口的定义

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

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

package mainimport "fmt"func main() {	var x interface{}	s := "你好啊"	x = s	fmt.Printf("type:%T value:%v\n", x, x)	i := 100	x = i	fmt.Printf("type:%T value:%v\n", x, x)	b := true	x = b	fmt.Printf("type:%T value:%v\n", x, x)}`type:string value:你好啊type:int value:100type:bool value:true``
9.2 空接口的应用9.2.1 空接口作为函数的参数

使用空接口类型可以接受任意类型的参数

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

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

// 空接口作为map的值var studentInfo = make(map[string]interface{})studentInfo["name"] = "sss"studentInfo["age"] = 18studentInfo["gender"] = truefmt.Println(studentInfo)
10 类型断言

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

10.1 接口值

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


要想判断空接口中的值,这个时候可以使用类型断言。

类型断言格式

x.(T)
x:表示类型为interface{}的变量T:表示x可能的类型

举个栗子:

func main() {	var x interface{}	x = "Hello 沙河"	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语言中的使用十分广泛。

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

总结

以上是内存溢出为你收集整理的12.Go语言干货-接口类型全部内容,希望文章能够帮你解决12.Go语言干货-接口类型所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1209660.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-04
下一篇 2022-06-04

发表评论

登录后才能评论

评论列表(0条)

保存