interface接口
1. Golang接口的定义
1.1. Golang 中的接口
- 在Go语言中接口(interface)是一种类型,一种抽象的类型。
- 接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节。
- 实现接口的条件
- 一个对象只要全部实现了接口中的方法,那么就实现了这个接口。
- 换句话说,接口就是一个需要实现的方法列表。
1.2. 定义一个Usber接口
- 定义一个 Usber 接口让 Phone 和 Camera 结构体实现这个接口
package main
import "fmt"
type User interface {
start()
end()
}
type Phone struct {
Name string
}
func (p Phone) start() {
fmt.Println(p.Name, "开机")
}
func (p Phone) end() {
fmt.Println(p.Name, "关机")
}
func main() {
p := Phone{Name: "Iphone"}
var p1 User
p1 = p
p1.start()
p1.end()
}
2. 空接口
2.1. 空接口说明
golang中空接口也可以直接当做类型来使用,可以表示任意类型
- Golang 中的接口可以不定义任何方法,没有定义任何方法的接口就是空接口。
- 空接口表示没有任何约束,因此任何类型变量都可以实现空接口。
- 空接口在实际项目中用的是非常多的,用空接口可以表示任意数据类型。
2.2. 空接口作为函数的参数
package main
import "fmt"
func show(a interface{}) {
fmt.Printf("type:%T value:%[1]v \n", a)
}
func main() {
show(20)
show("hello word")
slice := []int{1, 2, 3, 4}
show(slice)
}
2.3. 切片实现空接口
package main
import "fmt"
func main() {
var slice = []interface{}{1, 2, 3, 4}
fmt.Printf("type:%T value:%[1]v \n", slice)
}
2.4. map 的值实现空接口
package main
import "fmt"
func main() {
var aMap = make(map[string]interface{})
aMap["age"] = 123
aMap["name"] = "张三"
fmt.Printf("type:%T value:%[1]v \n", aMap)
}
3. 类型断言
- 一个接口的值(简称接口值)是由一个具体类型和具体类型的值两部分组成的。
- 这两部分分别称为接口的动态类型和动态值。
- 如果我们想要判断空接口中值的类型,那么这个时候就可以使用类型断言
- 其语法格式:
x.(T)
- x : 表示类型为 interface{}的变量
- T : 表示断言 x 可能是的类型
package main
import "fmt"
func main() {
var x interface{}
x = 123
v, ok := x.(string)
if ok {
fmt.Println("ok", v, ok)
} else {
fmt.Println("no", v, ok)
}
}
4. 值接收者和指针接收者
4.1. 值接收者
- 如果结构体中的方法是值接收者,那么实例化后的结构体值类型和结构体指针类型都可以赋值给接口变量
package main
import "fmt"
type User interface {
start()
end()
}
type Phone struct {
Name string
}
func (p Phone) start() {
fmt.Println(p.Name, "开机")
}
func (p Phone) end() {
fmt.Println(p.Name, "关机")
}
func main() {
i := Phone{Name: "苹果"}
var p1 User = i
p1.start()
p1.end()
m := &Phone{Name: "小米"}
var p2 User = m
p2.start()
p2.end()
}
4.2. 指针接收者
- 如果结构体中的方法是指针接收者,那么实例化后结构体指针类型都可以赋值给接口变量,
结构体值类型没法赋值给接口变量
。
package main
import "fmt"
type Usb interface {
start()
end()
}
type MyPhone struct {
Name string
}
func (p *MyPhone) start() {
fmt.Println(p.Name, "开启了Usb接口")
}
func (p *MyPhone) end() {
fmt.Println(p.Name, "结束了Usb接口")
}
func main() {
i := MyPhone{Name: "华为手机"}
var p Usb = &i
p.start()
p.end()
}
5. 一个结构体实现多个接口
package main
import "fmt"
type Age interface {
MyAge()
}
type Sex interface {
MySex()
}
type SetAgeAndSex interface {
SetMyInfo(*string, *int)
}
type My struct {
Sex string
Age int
}
func (m *My) SetMyInfo(s *string, a *int) {
m.Sex = *s
m.Age = *a
fmt.Println("修改信息")
}
func (m My) MySex() {
fmt.Println("我的性别为", m.Sex)
}
func (m *My) MyAge() {
fmt.Println("我", m.Age, "岁")
}
func main() {
my := &My{
Sex: "男",
Age: 998,
}
var age Age = my
var sex Sex = my
age.MyAge()
sex.MySex()
var setInfo SetAgeAndSex = my
s := "娚"
a := 18
setInfo.SetMyInfo(&s, &a)
age.MyAge()
sex.MySex()
}
6. 接口嵌套
package main
import "fmt"
type Append interface {
add()
}
type Delete interface {
pop()
}
type SliceMethod interface {
Append
Delete
}
type Slice []int
func (s *Slice) add() {
*s = append(*s, 6)
}
func (s *Slice) pop() {
*s = append((*s)[:2], (*s)[4:]...)
}
func run() *Slice {
s := &Slice{1, 2, 3, 4, 5}
fmt.Println(*s)
var sm SliceMethod = s
sm.add()
sm.pop()
return s
}
func main() {
s := run()
fmt.Println(*s)
}