- 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)
})
}
来源:oschina
链接:https://my.oschina.net/u/4280983/blog/4776128