一篇文章说清楚 golang之interface

目录

1、为什么interface{}函数可以保存任何类型的数据

2、interface 类型的数据如何转化为其他类型的数据

3、是不是所有的参数都能定义为interface类型?

4、什么情况下 需要抽象interface接口 


1、为什么interface{}函数可以保存任何类型的数据

这个需要从接口的本质说起,理解了本质就知道为什么了。

在go语言当中,interface是一种类型,同时也是一种抽象,一种结构。 内部是一组函数的集合。如果一个结构体实现了这个接口,也就是说 一个结构体的所有的方法当中,函数的名称、入参和出参与interface接口内部方法相同,签名相同。那么这个结构体就实现了这个接口库。

实现了之后,对象结构体的实例就可以当做变量传递给接口变量,接口变量就可以调用结构体的方法,来实现结构体自己的方法逻辑。

案例:

package main

import "fmt"

type Messager interface {
	Send()
}

type Msg struct {
	Content string
}

func (s *Msg) Send() {
	fmt.Printf("dear,%s", s.Content)

}

func NewMsg(content string) *Msg {
	return &Msg{
		Content: content,
	}

}

func main() {
	msg := NewMsg("how are you doing today")
	var msger Messager
	msger = msg
	msger.Send()

	// >>> dear,how are you doing today

}

示例代码当中,接口提Msg 实现了Messager 的接口,接口Messager 一共就只有一个 Send 的方法。所以 Msg 的实例对象就可以给 Messager 实例进行通过值的方式去传递。赋值给Messager 实例。

假设,有一个接口,这个接口 里面没有任何方法,就长像下面这样:

type Demo interface {
	
}

就是说,这个接口没有方法,所有的对象不需要满足接口方法签名就已经实现了它,所以 任何对象都可以 赋值给它。

案例:

package main

import (
	"fmt"
)

type Super interface {
}



type Person struct {
	Name string
}

func (p *Person) Eat() {
	fmt.Printf("%s is eating", p.Name)

}

type Animal struct {
	Name string
}

func (a *Animal) Run() {
	fmt.Printf("%s is running", a.Name)

}

func main() {


	var su1 Super
	var su2 Super

	pepple := &Person{"老王"}
	animal := &Animal{"老虎"}
	su1 = pepple
	res := su1.(*Person)
	fmt.Printf("su 中保存的是:%v\n", res)
	su2 = animal
	info := su2.(*Animal)
	fmt.Printf("su 中保存的是:%v\n", info)

}

'''
>>>
su 中保存的是:&{老王}
su 中保存的是:&{老虎}

'''

我们看Super 接口可以保存不同类型的结构,不仅可以保存Pepple,还可以保存Animal. 就是这个原因。任何类型都可以保存。

2、interface 类型的数据如何转化为其他类型的数据

比如下面代码就会报错

package main

import "fmt"

func Add(a, b interface{}) int {

	return a + b

}

func main() {
	res := Add(3, 8)
	fmt.Println(res)

}

.\main.go:7:9: invalid operation: operator + not defined on a (variable of type interface{})

经常会遇到类似的场景。原因其实是这样,因为虽然interface可以保存任何类型数据,但是 还是interface 类型,你需要转化为原有数据类型才能进行其他操作。

如何做呢?

只需要通过类型断言的方法就可以获取到接口保存的值。

完整代码如下

package main

import "fmt"

func Add(a, b interface{}) int {
	num1 := a.(int)
	num2 := b.(int)
	return num1 + num2

}

func main() {
	res := Add(3, 8)
	fmt.Println(res)

}

''' output
>>>
11

'''

3、是不是所有的参数都能定义为interface类型?

其实通过空接口保存数据,从效率层面来说是比较慢的,如果参数类型确定,肯定是对应的类型比较合适,所以见多一些为了拓展性和兼容性,全部都是interface类型的参数,你怎么看?

4、什么情况下 需要抽象interface接口 

如果需求不会设计很多类场景,功能相同,但是逻辑不通,比较单一,那么结构体方法就够了。

但是是如果涉及到很多不同的业务逻辑,比如同样是发消息,有发短息,发微信,邮件,企业微信登,这样的场景 就可以抽象通用接口。然后用不同的结构体去实现自己不同的逻辑。

  • 41
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值