概述
go的接口是一个很重要的类型,接口类型的变量存储了两个内容:1.实际的值 2.这个值的类型描述,在下面的代码实例中得到验证
特点
0.接口约定:接口类型中定义的方法即为约定,若一个具体类型实现了所有这些方法,则该类型就满足该接 口的约定,或者说它是这个接口类型的实例(实现了该接口)。
1.可替换性(里氏替换原则):满足相同接口约定的类型之间可进行相互替换。例如:若一个方法的形参定义为接口类型,那么它可以接收任何满足该接口约定的类型的实参。
2.接口值的零值:动态类型type和对应的动态值value均为nil,如var w io.Writer
3.接口值:即接口变量的值,由两个部分组成,一个具体的类型和那个类型的值。它们被称为接口的动态类型和动态值
4.空接口值:当且仅当接口的动态类型type和对应的动态值value均为nil时,才为空接口值,此时它等于nil,interface{},它表示空的方法集合,由于任何值都有零个或者多个方法,所以任何值都可以满足它。
5.一个接口值可以持有任意大的动态值,不论动态值多大,接口值总是可以容下它
6.使用接口时,直接声明一个接口类型的变量,然后再对它赋值,之后使用该变量时,就可以直接把它和nil比较来判断是否为空接口
7.接口指向的对象可以是一个指针,也可以是一个对象,也就是可以给一个接口指针赋值,也可以是对象赋值
实例
package baseai
import "testing"
import "fmt"
type ITest interface {
}
type IWrite interface {
Hello()
}
type IFile interface {
Read()
Write()
}
type IReader interface {
Read()
}
type File struct {
WHO string
}
func (f *File) Read() {
}
func (f *File) Write() {
}
func TestInterface(t *testing.T) {
var f0 IReader = &File{WHO: "hello"} //File只实现了IReader的所有接口,所以f0是IReader类型
if ff, ok := f0.(IReader); ok {
fmt.Println(ff) //&{hello}
fmt.Println("the type f0 is IReader")
} else {
fmt.Println(ff)
fmt.Println("the type f0 is not IReader")
}
var f1 IReader = new(File) //File只实现了IReader的所有接口
if ff, ok := f1.(IWrite); ok { //File 并没有实现IWrite的接口,所以f1不是IWrite类型
fmt.Println(ff) //<nil>
fmt.Println("the type f1 is IWrite")
} else {
fmt.Println(ff)
fmt.Println("the type f1 is not IWrite")
}
var f3 IReader = new(File) //File只实现了IReader的所有接口,所以f3是IReader类型
if ff, ok := f3.(IFile); ok { //File实现了IFile的所有接口,所以f3也是IFile类型
fmt.Println(ff)
fmt.Println("the type f3 is IFile")
} else {
fmt.Println(ff)
fmt.Println("the type f3 is not IFile")
}
var f4 interface{} = new(File)
if ff, ok := f4.(*File); ok {
fmt.Println(ff)
fmt.Println("the type f4 is *File")
} else {
fmt.Println(ff)
fmt.Println("the type f4 is not *File")
}
var f5 IReader = new(File)
if ff, ok := f5.(*File); ok {
fmt.Println(ff)
fmt.Println("the type f5 is *File")
} else {
fmt.Println(ff)
fmt.Println("the type f5 is not *File")
}
}
func TestBaseType(t *testing.T) {
var a int32 = 1
var id interface{} = a //也可以&a
if ff, ok := id.(int32); ok {//如果&a,这里就是id.(*int32)
fmt.Println(ff)
fmt.Println("the type id is int32")
} else {
fmt.Println(ff)
fmt.Println("the type id is not int32")
}
}
=== RUN TestInterface
&{hello}
the type f0 is IReader
<nil>
the type f1 is not IWrite
&{}
the type f3 is IFile
&{}
the type f4 is *File
&{}
the type f5 is *File
--- PASS: TestInterface (0.00s)
=== RUN TestBaseType
1
the type id is int32
--- PASS: TestBaseType (0.00s)
PASS
ok command-line-arguments 3.469s