Golang interface 接口的应用场景 使用细节

接口应用场景


对初学者讲,理解接口的概念不算太难,难的是不知道什么时候使用接口,下面我例举几个应用场景:

1.说现在美国要制造轰炸机,武装直升机,专家只需把飞机需要的功能/规格定下来即可,然后让别的人具体实现就可。

要去写一个结构体,结构体里面有些方法,这些方法让一个程序员去写肯定是不太好的,希望将每个人都动起来,可以找项目经理,项目经理去定义一个接口,大家去实现这个接口就完事了。这样就可以很好的控制管理项目的进度。

其实也就是取定义规范,其他人将规范实现即可。

你想要去排序,只需要取实现这个data接口就行了。 

其实也就是传入实现了interface接口的方法全部实现的,那么就可以去调用包里面的sort方法,将这个类型传入进去即可。 

sort包里面有一个Sort函数,sort里面接受data,它是一个接口,那么只要传进去的变量实现了接口Interface里面所有方法,传入进去,它自然就给你排序了。当你实现接口,那么Sort函数就会自动帮你实现排序。

如果如下所示,之前使用email发送告警信息,后面如果要换成dingding去发送告警,那么代码就需要改动。 

//如果产生了一个告警,将告警发送给相关的人
//email sms weixin

type EmailSender struct {

}

type DingDingSender struct {
	
}

func (e *EmailSender) Send(msg string) error {
	fmt.Println(msg)
	return nil
}

func (d *DingDingSender) Send(msg string) error{
	fmt.Println(msg)
	return nil
}

func test(e *EmailSender,msg string)  {
	e.Send(msg)
}

func main()  {
	sender := new(EmailSender)
	sender.Send("email send")
}

如果需要改动得修改如下,要将和email相关的代码全部修改,如果没有全部修改会导致编译的时候失败。

为了解决这种问题,可以定义接口,这些结构体有个特点就是都有Send方法,这样就可以定义只有Send方法接口,那么参数类型就可以使用接口类型。

如果定义了接口就方便多了,只需要改一个地方,也就是结构体实例化的地方即可

type Sender interface {
	Send(string) error
}

	sender := new(DingDingSender)
	test(sender,"dingding send")
	
    sender1 := new(EmailSender)
	test(sender1,"email send")

2.说现在有一个项目经理,管理三个程序员,功能开发一个软件,为了控制和管理软件,项目经理可以定义一些接口,然后由程序员具体实现。

项目经理只需要将接口定义好,剩下的让程序员a b c共同完成。这样就可以控制软件的开发进度。

注意事项和细节


1)接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量(实例)

type interfaceA interface {
	Say()
}

type Student struct {
}

func (*Student) Say() {
	fmt.Println("I am a student")
}

func main() {
	var i interfaceA
	student := new(Student)
	i = student //结构体变量实现了接口的方法
	i.Say()
}

2)接口中所有的方法都没有方法体,即都是没有实现的方法。

3)在Golang中,一个自定义类型需要将某个接口的所有方法都实现,我们说这个自定义类型实现了该接口。

4)一个自定义类型只有实现了某个接口,才能将该自定义类型的实例(变量)赋给接口类型。

5)只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型。

type interfaceA interface {
	Say()
}

type integer int

func (i *integer) Say() {
	fmt.Println("i地址为:", &i, "i的值为:", *i)
}

func main() {
	var i interfaceA
	var a integer = 5
	a.Say()
}

6)一个自定义类型可以实现多个接口

7)Golang接口中不能有任何变量

上面可以看到和传统的oop不一样,他是基于方法来实现的这个接口。而java这些它是显示实现的,必须显示的指定去实现哪个接口。而golang并不关心实现了哪个接口,只关心实现了哪个方法。

8)一个接口(比如 A接口)可以继承多个别的接口(比如 B,C接口),这时如果要实现A接口也必须将B,C接口的方法也全部实现。

可以看到A接口里面有两个方法,相当于将这两个接口继承下来了。那么就要将继承下来的接口里面的方法和本身的方法都去实现。

9) interface类型默认是一个指针(引用类型),如果没有对interface初始化就使用,那么会输出nil(在传入参数的时候,比如结构体,传入的不是值类型,传入的是引用类型,也就是&struct{}

10)空接口interface没有任何方法,所以所有类型都实现了空接口(空接口其实就是一种数据类型,可以将任何的数据类型的变量赋值给空接口,如果参数是空接口的形参,那么意味着可以接受任何一种数据类型)

下面可以看到结构体默认实现了空接口,其他类型也可以,字符串整型这些都是可以的。

type T interface {
}

type student struct {
	age  int
	name string
}

func main() {
	s := &student{
		age:  10,
		name: "lucas",
	}
	var t T = s
	fmt.Println(reflect.TypeOf(t))
	fmt.Println(t)

	var t3 interface{} = s
	fmt.Println(t3)
}

*main.student
&{10 lucas}
&{10 lucas}

可以将任何的变量赋值给空接口

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值