接口类型
go语言中接口(interface)是一种类型,一种抽象的类型。
interface是一组method的集合,是duck-type programming的一种体现。接口做的事情就像是定义一个协议(规则),只要一台机器有洗衣服和甩干的功能,我就称它为洗衣机。不关心属性(数据),只关心行为(方法)。
空接口
空接口的定义
interface{} 类型,空接口。interface{} 类型是没有方法的接口。由于没有 implements 关键字,所以所有类型都至少实现了 0 个方法,所以 所有类型都实现了空接口。这意味着,如果编写一个函数以 interface{} 值作为参数,那么可以为该函数提供任何值。
func main() {
// 定义一个空接口x
var x interface{}
s := "Hello11"
x = s
fmt.Printf("type:%T value:%v\n", x, x)
i := 100
x = i
fmt.Printf("type:%T value:%v\n", x, x)
b := true
x = b
fmt.Printf("type:%T value:%v\n", x, x)
}
空接口作为map的值
package main
import "fmt"
//空接口
type null1 interface {}
//空接口可做任意类型 做map值 任意数值
func main() {
map1 := make(map[string]interface{},100)
map1["z"] = 100
map1["d"] = "ll"
map1["ture"] = true
fmt.Println(map1)
}
类型断言
空接口可以存储任意类型的值,那我们如何获取其存储的具体数据呢?
想要判断空接口中的值这个时候就可以使用类型断言,其语法格式:
x.(T)
其中:
- x:表示类型为interface{}的变量
- T:表示断言x可能是的类型。
该语法返回两个参数,第一个参数是x转化为T类型后的变量,第二个值是一个布尔值,若为true则表示断言成功,为false则表示断言失败。
func main() {
var a interface{}
a = "1111"
v, ok := a.(string)
if ok {
fmt.Println(a)
} else {
fmt.Println("failed")
}
}
值接收者和指针接收者实现接口的区别
//定义动物接口类型
type animal interface {
speak()
move()
}
type cat struct {
name string
}
//值接受者---------------------
/*
func (c cat) speak() {
fmt.Println("miao")
}
func (c cat) move() {
fmt.Println("move11")
}
func main() {
var a animal
var b animal
ling1 := cat{"lingling"}
tom := &cat{"xiaohua"} //语法糖 xiangdangyu *tom := &cat
a = tom
b = ling1
tom.speak() // (*tom.speak())
fmt.Println(a)
}
使用值接收者实现接口之后,不管是cat结构体还是结构体指针cat类型的变量都可以赋值给该接口变量。因为Go语言中有对指针类型变量求值的语法糖,cat指针内部会自动求值tom。
//指针接受者---------------------
func (c *cat) speak() {
fmt.Println("miao")
}
func (c *cat) move() {
fmt.Println("move11")
}
func main() {
var a animal
tom := &cat{"xiaohua"} //语法糖 xiangdangyu *tom := &cat
a = tom
tom.speak() // (*tom.speak())
a.move()
}
此时实现接口的是cat类型,所以不能给a传入cat类型的tom,此时a只能存储cat类型的值。