Go的interface

守給你的承諾、 提交于 2020-12-05 16:54:50
  • Go中的interface也是类型type,定义了方法规范,其内只有方法的声明没有实现,定义格式为:type interface_Name interface{ f1()....}
  • 需要注意的一点是go中的interface是非侵入式的,也就是不需要利用某个关键字(比如Java中的implements)显示的声明某个类型是否实现了某个interface,只需要某个类型的对象的某个方法是某个接口的方法的实现(go中不允许方法的重载),就表明该对象(其实是其指针类型!!!)实现了该接口,其是该接口的一个实例
  • go中的接口不要求其内的方法均为导出的,可以定义私有,或者导出的方法声明(跟Java中接口很不一样)
  • 接口中所有的方法都必须被实现
  • Go语言的接口在命名时,一般会在单词后面添加er,如写操作的接口叫做Writer
  • 一个类型可以实现多个接口,接口间是彼此独立的,互相不知道对方的实现多个类型也可以实现相同的接口
  • 接口之间也可以相互嵌套
  • 空接口是接口的特殊形式,没有任何方法,因此任何具体的类型都可以认为其默认实现了空接口!!!interface{}//空接口类型,所以一旦一个方法的参数是一个空接口类型,表明该方法可以接受任何具体的类型作为其参数,也可以利用空接口,可以实现任意类型的存储
//空接口作为函数参数:

func Test(i interface{}) {
	fmt.Printf("%T\n", i)
}

func main() {
	Test(3)			// int
	Test("hello")	// sting
}
// 利用空接口,可以实现任意类型的存储:

	m := make(map[string]interface{})
	m["name"] = "李四"
	m["age"] = 30	

【补充:空接口相关操作】:

1、从空接口类型中获取值:

保存到空接口的值,如果直接取出指定类型的值时,会发生编译错误:

var a int = 1
var i interface{} = a
var b int = i				//这里编译报错(类型不一致),可以这样做:b := i

2、空接口类型对象或变量值的比较

2.1类型不同的空接口比较:

var a interface{} = 100
var b interface{} = "hi"

fmt.Println(a == b)			//false

2.2 不能比较空接口中的动态值:

var c interface{} = []int{10}
var d interface{} = []int{20}
fmt.Println(c == d)					//运行报错

2.3 空接口的类型和可比较性总结:

类型 说明
map 不可比较,会发生宕机错误
切片 不可比较,会发生宕机错误
通道 可以比较,必须由同一个make生成,即同一个通道才是true
数组 可比较,编译期即可知道是否一致
结构体 可比较,可逐个比较结构体的各成员
函数 可比较
package demo

import "fmt"

/*
@Author:David Ma
@Content:接口相关定义
@Date:2020-12-03 15:24
*/
type EatService interface {
	Eat()
	Sleep()
}

type Cat struct {
	Name string
}

func (cat *Cat)Eat()  {
	fmt.Printf("%s eatting \n", cat.Name)
}

func (cat *Cat) Sleep() {
	fmt.Printf("%s sleeping\n", cat.Name)
}

type Dog struct {
	Name string
}

func (dog *Dog) Sleep() {
	fmt.Printf("%s sleeping\n", dog.Name)
}

func (dog *Dog)Eat()  {
	fmt.Printf("%s eatting \n", dog.Name)
}

func MyEat(es EatService)  {
	es.Eat()
}
func MySleep(es EatService)  {
	es.Sleep()
}
package test

import (
	"../demo"
	"testing"
)

/*
@Author:David Ma
@Content:接口相关定义
@Date:2020-12-03 15:24
*/

func TestMyInterface(t *testing.T)  {
	t.Helper()
	t.Run("", func(t *testing.T) {
		cat := demo.Cat{"Tom"}
		dog := demo.Dog{"Jerry"}
		// 注意这里要传一个指针类型,因为是指针类型(* Dog以及* Cat)实现了EatService接口,而不是Dog和Cat,也就是只有*Dog或者*Cat类型才可以看作是EatService类型)
		//否则compile error:Cannot use 'cat' (type Cat) as type EatService Type does not implement 'EatService' as 'Eat' method has a pointer receiver
		demo.MyEat(&cat)
		demo.MySleep(&cat)
		//如果对象实现了接口的某个方法,则其必须实现该接口的其他方法,否则报错:
		//Cannot use '&dog' (type *Dog) as type EatService Type does not implement 'EatService' as some methods are missing: Sleep()
		demo.MyEat(&dog)
		demo.MySleep(&dog)
	})
}

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!