一个具体类型实现接口不需要再语法上显示地声明,只要具体类型的方法集是接口方法集的超集,就代表实现类该接口。
接口没有具体实现逻辑,不能定义字段
不能
a int
空接口
方法集为空,任意类型都实现了空接口,任意类型都可以赋值或传递给空接口,包括非命名类型的实例
非命名类型不能定义自己的方法,方法集为空,所以其类型变量只能传递给空的接口。
基本概念
接口声明
接口分类
- 接口字面量
- 接口命名类型
声明方法:
interface
接口字面量:
interface{
methodsignature1//方法声明
..
}
接口字面量用的少,主要空接口声明才会用到
接口命名类型:
type InterfaceName interface{
mathodsignature1
...
}
接口大括号内可以放方法声明和另一个接口的匿名字段,放后者编译器会自动展开
type Reader interface{
Read(p []byte) (n int, err error)//方法声明
}
//以下会自动展开
type ReadWriter interface{
Reader
Writer(p []byte)(n int,err error)
}
//等价于下面的
type ReadWriter interface{
Read(p []byte) (n int, err error)//方法声明
Writer(p []byte)(n int,err error)
}
方法声明
方法声明=方法名+方法签名
mathodName (InputtypeList)Out
Writer([]byte)(int, error)
接口匹配时会校验 方法名称和方法签名,即方法声明
接口初始化
没有初始化的接口变量,默认值为nil
var i io.Reader//i=nil
初始化方法:
- 变量赋值接口
类型实例赋值给接口类型变量,实例的方法集要时接口的方法集的超集 - 接口变量赋值接口变量
大的赋给小的
file,_ =os.openFile("notes.txt",os.O_RDWR|os.O_CREATE, 0755)
var rw io.ReadWriter = file
//io .ReadW riter 接口可以直接赋位给io.Writ er 接口交量
var w 工o.Writer = rw
接口方法的调用
初始化后的接口变量就可以调用方法
p:=[]byte{1,2,3}
w.Writer(p)
接口的动态类型和静态类型
动态类型
接口绑定的具体实例的类型
静态类型
接口定义时就确定的类型,本质是 接口的方法签名集合。
两个接口如果方法签名集合相同,顺序可以不同,这两个接口可以相互赋值(因为大的可以给小的赋值,反之不行)
接口运算
初始化
检查接口类型:确定接口变量绑定的具体实例是什么类型,
这个实例是否实现了其他接口
类型断言
i.TypeName
i是接口变量,Typename是 接口类型名或具体类型名
- 如果是具体类型名,断言用于判断接口i绑定的实例类型是否为Typename
- 如果是接口类型名,断言用于判断i绑定的实例是否同时实现了Typename
o:= i.(TypeName)
用法
if o , ok : = i.(TypeName) ; ok {
}
//如果i是typename类型或实现了该接口,则返回true,o就是i的副本
使用举例:
type Inter interface {
Ping()
Pang()
}
type St struct{
Name string
}
func (St) Ping(){
print("ping")
}
func (*St) Pang(){
print("pang")
}
func main(){
st := &St{"12"}
var i interface{}=st
if o , ok := i.(*St); ok {
o.Ping() //ping
o.Pang() //pang,
}else {
print("error")
}
}
类型查询
switch v := i.(type) {
case type1,type2:
xxx
default:
xx
}
接口优点和使用形式
优点:
- 解耦:
层与层之间用接口进行抽象和解耦 - 实现泛型:
暂时还不支持泛型
使用形式:
- 作为结构内嵌字段
- 作为函数或方法的形参,返回值
- 作为其他接口定义的嵌入字段
空接口
基本概念
没有任何方法的接口。
类似java的object
int 也符合空接口
用途
弥补泛型:
func Fprint(w io.Writer, a...interface{}) (n int, err error)
//接收一个任意参数a
反射:
后面介绍
空接口和nil
空接口有两个字段:实例类型和指向绑定实例的指针。两个都为nil时,接口为nil
var st *St = nil
var it Inter = st//it的实例类型时nil,但是指针不是nil,所以it !=nil
//此时it是一个接口指针,只能调用inter的*S方法集,而不能调用S方法集
接口内部实现
跳过。。