type iface struct {
tab *itab
data unsafe.Pointer
}
不能有字段
不能定义自己的方法
只能声明方法,不能实现
可嵌入其他接口类型
接口通常以er作为名称后缀,方法名是声明组成部分,但参数名可不同或省略
type tester interface {
test()
string() string
}
type data struct {
}
func (*data) test() {}
func (data) string() string {
return ""
}
func main() {
var d data
//var t tester = d //错误: data does not implement tester(test method has pointer receiver)
var t tester = &d
t.test()
println(t.string())
}
type stringer interface {
string() string
}
type tester interface {
stringer //嵌入其他接口
test()
}
type data struct {}
func (*data) test() {
println("this is test()")
}
func (data) string() string {
return "this is string()"
}
func main() {
var d data
var t tester = &d
t.test()
println(t.string())
}
超集接口变量可隐式转换为子集,反过来不行
支持匿名接口类型,可直接用于变量定义,或作为结构字段类型
type data struct {
}
func(data) string() string {
return "this is string()"
}
type node struct {
data interface{ //匿名接口类型
string() string
}
}
func main() {
var t interface{ //定义匿名接口变量
string() string
} = data{}
n := node{
data:t,
}
println(n.data.string())
}
7.2执行机制(看不懂暂时不写)
接口使用一个名为itab的结构存储运行期所需要的相关类型信息。
利用调试器,我们可查看这些结构存储的具体内容
7.3 类型转换
类型推断可将接口变量还原为原始类型,或用来判断是否实现了某个更具体的接口类型
type data int
func (d data) String() string {
return fmt.Sprintf("data:%d", d)
}
func main() {
var d data = 15
var x interface{} = d
if n, ok := x.(fmt.Stringer); ok { //转换为更具体的接口类型
fmt.Println(n)
}
if d2, ok := x.(data); ok { //转换回原始类型
fmt.Println(d2)
}
e := x.(error) //错误:main.data is not error
fmt.Println(e)
}
func main() {
var x interface{} = func(x int) string {
return fmt.Sprintf("d:%d", x)
}
switch v := x.(type) {
case nil:
println("nil")
case *int:
println(*v)
case func(int) string:
println(v(100))
case fmt.Stringer:
fmt.Println(v)
default:
println("unknown")
}
}
7.4 技巧
让编译器检查,确保类型实现了指定接口
type x int
func init() { //包初始化函数
var _ fmt.Stringer = x(0)
}
/*
cannot use x(0) (type x ) as type fmt.Stringer in assignment
x does not implement fmt.Stringer (missing String method)
*/
定义函数类型,让相同签名的函数自动实现某个接口
type FuncString func() string
func( f FuncString) String() string {
return f()
}
func main() {
var t fmt.Stringer = FuncString(func() string { //转换类型,使其实现Stringer接口
return "hello World";
})
fmt.Println(t)
}