6 接口
接口类型是由一组方法签名定义的集合。
接口类型的变量可以保存任何实现了这些方法的值。
package main
import "fmt"
type iii interface {
fff()
}
type kkk int
func (v kkk) fff() {
fmt.Println("kkk type")
}
type lll float64
func (v *lll) fff() {
fmt.Println("lll type")
}
func main() {
var i iii
k := kkk(12)
l := lll(12.4)
i = k
i.fff()
i = &l
i.fff()
}
7 接口与隐式实现
类型通过实现一个接口的所有方法来实现该接口,既然无需专门显示声明,也就没有"implements"关键字。
隐式接口从接口的实现中解耦了定义,这样的接口可以出现在任何包中,无需提前准备。
8 接口值
在内部,接口值可以看作包含值和具体类型的元组:(value, type)。
接口值保存了一个具体底层类型的具体值。
接口值调用方法时会执行其底层类型的同名方法。
package main
import (
"fmt"
"math"
)
type I interface {
M()
}
type T struct {
S string
}
func (t *T) M() {
fmt.Println(t.S)
}
type F float64
func (f F) M() {
fmt.Println(f)
}
func main() {
var i I
i = &T{"Hello"}
describe(i)
i.M()
i = F(math.Pi)
describe(i)
i.M()
}
func describe(i I) {
fmt.Printf("(%v, %T)\n", i, i)
}
9 底层值为nil的接口值
即便接口内的具体值为nil,方法仍然会被nil接收者调用。
注意:保存了nil具体值的接口其自身并不为nil。
package main
import "fmt"
type iii interface {
f()
}
type sss struct{
x, y int
}
func (sp *sss) f() {
if sp == nil {
fmt.Println("empty")
return
}
fmt.Println("ssss")
return
}
func main() {
var i iii
var s *sss
i = s
i.f()
}
10 nil 接口值
nil接口值既不保存值,也不保存具体类型。
为nil接口调用方法会产生运行时错误,因为接口的元组内并未包含能够指明该调用哪个具体方法的类型。
package main
import "fmt"
type iii interface{
fff()
}
func main() {
var i iii
fmt.Printf("%v %T \n", i)
}
11 空接口
指定了零个方法的接口值被称为空接口。
interface{}
空接口可保存任何类型的值。(因为每个类型都至少实现了零个方法。)
空接口用于处理位置类型的值。例如,fmt.Print可接受类型为interface{}的任意数量的参数。
package main
import "fmt"
func main() {
var i interface {}
fmt.Printf("%T %v\n", i, i)
i = 42
fmt.Printf("%T %v\n", i, i)
i = "hhh"
fmt.Printf("%T %v\n", i, i)
}