3.7、Golang接口 interface
go语言中的接口,是一种新的类型定义,它把所有的具有共性的方法定义在一起,任何其他类型制药实现了这些方法就是实现了这个接口
语法
go
// 定义接口
type interface_name interface {
method_name [return_type]
...
}
// 定义结构体
type struct_name struct {
}
// 实现接口方法
func (struct_name_variable struct_name) method_name [return_type]{
// 方法实现
}
接口示例
定义一个USB接口,有读read 写write两个方法
再定义一个电脑computer 和 手机Mobile 来实现这个接口
go
package main
import "fmt"
// USB接口
type USB interface {
read()
write()
}
// Computer 结构体
type Computer struct {
}
// Mobile 结构体
type Mobile struct {
}
// Computer 实现USB方法
func (computer Computer) read() {
fmt.Println("computer read")
}
func (computer Computer) write() {
fmt.Println("computer write")
}
// Mobile 实现USB方法
func (mobile Mobile) read() {
fmt.Println("mobile read")
}
func (mobile Mobile) write() {
fmt.Println("mobile write")
}
func main() {
computer := Computer{}
computer.read()
computer.write()
// computer read
// computer write
mobile := Mobile{}
mobile.read()
mobile.write()
// mobile read
// mobile write
}
备注: 实现接口必须实现接口中的所有方法
golang接口值类型接收者和指针类型接收者
示例
go
package main
import "fmt"
// 定义接口
type Pet interface {
eat()
}
// 定义结构体
type Dog struct {
name string
}
func (dog Dog) eat() {
fmt.Println("dog eat")
}
func main() {
dog := Dog{name: "Tom"}
dog.eat()
// dog eat
}
golang接口和类型的关系
- 一个类型可以实现多个接口
- 多个类型可以实现同一个接口(多态)
一个类型可以实现多个接口
示例
Music接口可以播放音乐 Video接口可以播放视频
手机Mobile实现这两个接口,即可以播放音乐,又可以播放视频
go
package main
import "fmt"
// 定义接口
type Music interface {
playMusic()
}
type Video interface {
playVideo()
}
// 定义结构体
type Mobile struct {
}
func (m Mobile) playMusic() {
fmt.Println("Mobile playMusic")
}
func (m Mobile) playVideo() {
fmt.Println("Mobile playVideo")
}
func main() {
m := Mobile{}
m.playMusic()
// Mobile playMusic
m.playVideo()
// Mobile playVideo
}
多个类型可以实现同一个接口(多态)
示例
一个宠物接口Pet,猫Cat和狗Dog都可以实现该接口
go
package main
import "fmt"
// 定义接口
type Pet interface {
eat()
}
// 定义结构体
type Dog struct {
}
type Cat struct {
}
func (dog Dog) eat() {
fmt.Println("dog eat")
}
func (cat Cat) eat() {
fmt.Println("cat eat")
}
func main() {
dog := Dog{}
dog.eat()
// dog eat
cat := Cat{}
cat.eat()
// cat eat
// 声明接口变量
var pet Pet
pet = dog
pet.eat()
// dog eat
pet = cat
pet.eat()
// cat eat
}
golang接口嵌套
示例
飞鱼,既可以飞,也可以游泳,
飞鱼接口有两个接口组成:飞Fly接口,游泳Swim接口
go
package main
import "fmt"
// 定义接口
type Flyer interface {
fly()
}
// 定义接口
type Swimmer interface {
swim()
}
// 组合接口
type FlyFish interface {
Flyer
Swimmer
}
// 结构体
type Fish struct{}
// 实现方法
func (fish Fish) fly() {
fmt.Println("fish fly")
}
func (fish Fish) swim() {
fmt.Println("fish swim")
}
func main() {
var fly FlyFish
fly = Fish{}
fly.fly()
// fish fly
fly.swim()
// fish swim
}
通过接口实现OCP设计原则
开闭原则 Open-Closed Principle
对扩展开放,对修改关闭
示例
go
package main
import "fmt"
// 定义接口
type Pet interface {
eat()
sleep()
}
// 定义结构体
type Dog struct {
}
type Cat struct {
}
// Dog 实现 Pet接口
func (dog Dog) eat() {
fmt.Println("dog eat")
}
func (dog Dog) sleep() {
fmt.Println("dog sleep")
}
// Cat 实现 Pet接口
func (cat Cat) eat() {
fmt.Println("cat eat")
}
func (cat Cat) sleep() {
fmt.Println("cat sleep")
}
// 结构体
type Person struct{}
// 参数既可以是Dog 也可以是 Cat
func (person Person) care(pet Pet) {
pet.eat()
pet.sleep()
}
func main() {
dog := Dog{}
cat := Cat{}
person := Person{}
person.care(dog)
// dog eat
// dog sleep
person.care(cat)
// cat eat
// cat sleep
}
golang模拟OOP的属性和方法
golang中没有面向对象的概念,也没有封装的概念,但是可以通过而机构提struct和函数绑定来实现OOP的属性和方法
示例
Person类
- 属性: name、age
- 方法:eat、sleep、work
go
package main
import "fmt"
// 属性
type Person struct {
name string
age int
}
// 方法
func (person Person) eat() {
fmt.Println("person eat")
}
func (person Person) sleep() {
fmt.Println("person sleep")
}
func (person Person) wrok() {
fmt.Println("person wrok")
}
func main() {
person := Person{
name: "Tom",
age: 23,
}
person.eat()
// person eat
person.sleep()
// person sleep
person.wrok()
// person wrok
}
golang继承
通过结构体嵌套来实现继承
go
package main
import "fmt"
// 定义结构体
type Pet struct {
name string
age int
}
func (pet Pet) eat() {
fmt.Println("pet eat")
}
func (pet Pet) sleep() {
fmt.Println("pet sleep")
}
// 定义结构体
type Dog struct {
// 匿名
Pet
}
type Cat struct {
pet Pet
}
func main() {
dog := Dog{
Pet{name: "Tom", age: 23},
}
// 匿名直接调用
dog.eat()
// pet eat
cat := Cat{
pet: Pet{name: "Tom", age: 23},
}
// 通过属性pet 调用
cat.pet.eat()
// pet eat
}
golang构造函数
golang中没有构造函数的概念,可以使用函数来模拟构造函数的功能
go
package main
import "fmt"
type Person struct {
name string
age int
}
func NewPerson(name string, age int) (*Person, error) {
if name == "" {
return nil, fmt.Errorf("name不能为空")
}
if age < 0 {
return nil, fmt.Errorf("age不能小0")
}
return &Person{name: name, age: age}, nil
}
func main() {
person, err := NewPerson("Tom", 23)
if err == nil {
fmt.Printf("%v\n", person)
// &{Tom 23}
} else {
fmt.Printf("%v\n", err)
}
}