Go 接口
接口定义
Go语言提倡面向接口编程。
指针接收者实现接口
package main
import "fmt"
// 接口定义
type USB interface {
Connect()
Disconnect()
}
type Laptop struct {
name string
version string
}
type Desktop struct {
name string
version string
}
// 实现USB接口
func (laptop *Laptop) Connect() {
fmt.Println("USB Connecting to", laptop.name)
}
func (laptop *Laptop) Disconnect() {
fmt.Println("USB Disconnecting from", laptop.name)
}
func (desktop *Desktop) Connect() {
fmt.Println("USB Connecting to", desktop.name)
}
func (desktop *Desktop) Disconnect() {
fmt.Println("USB Disconnecting from", desktop.name)
}
func main() {
var legion_laptop Laptop = Laptop{
name: "Legion Y7000P",
version: "2022",
}
var legion_desktop2 *Desktop = &Desktop{
name: "Legion Y9000P",
version: "2023",
}
var legion_desktop Desktop = Desktop{
name: "Legion Desktop Computer",
version: "2023",
}
var x USB = legion_laptop
x.Disconnect()
x.Connect()
x = legion_desktop2
x.Connect()
x.Disconnect()
x = legion_desktop
x.Connect()
x.Disconnect()
}
当我们写成这样的时候,可以看到
也就是说,当我们使用指针接收者的时候,是不能传递结构体变量给接口变量的
值接收者实现接口
package main
import "fmt"
// 接口定义
type USB interface {
Connect()
Disconnect()
}
type Laptop struct {
name string
version string
}
type Desktop struct {
name string
version string
}
// 实现USB接口
func (laptop Laptop) Connect() {
fmt.Println("USB Connecting to", laptop.name)
}
func (laptop Laptop) Disconnect() {
fmt.Println("USB Disconnecting from", laptop.name)
}
func (desktop Desktop) Connect() {
fmt.Println("USB Connecting to", desktop.name)
}
func (desktop Desktop) Disconnect() {
fmt.Println("USB Disconnecting from", desktop.name)
}
func main() {
var legion_laptop Laptop = Laptop{
name: "Legion Y7000P",
version: "2022",
}
var legion_desktop2 *Desktop = &Desktop{
name: "Legion Y9000P",
version: "2023",
}
var legion_desktop Desktop = Desktop{
name: "Legion Desktop Computer",
version: "2023",
}
var x USB = legion_laptop
x.Disconnect()
x.Connect()
x = legion_desktop2
x.Connect()
x.Disconnect()
x = legion_desktop
x.Connect()
x.Disconnect()
}
我们可以发现,使用值接收者实现接口之后,不管是Laptop的结构体还是其结构体指针,都可以赋值给接口变量
一个类型实现多个接口
一个类型可以同时实现多个接口,而接口间彼此独立,不知道对方的实现
package main
import "fmt"
type Payer interface {
Pay()
}
type Talker interface {
Talk()
}
type AliPay struct {
}
type Wechat struct {
}
func (w Wechat) Pay() {
fmt.Println("Wechat Pay")
}
func (w Wechat) Talk() {
fmt.Println("Wechat Talk")
}
func (a AliPay) Pay() {
fmt.Println("AliPay Pay")
}
func (a AliPay) Talk() {
fmt.Println("AliPay Talk")
}
func main() {
var payer Payer = AliPay{}
payer.Pay()
payer = Wechat{}
payer.Pay()
var talker Talker = Wechat{}
talker.Talk()
talker = AliPay{}
talker.Talk()
}
接口嵌套
接口与接口间可以通过嵌套创造出新的接口。
package main
import "fmt"
type Payer interface {
Pay()
}
type Talker interface {
Talk()
}
type AliPay struct {
}
type Wechat struct {
}
type Tooler interface {
Payer
Talker
}
func (w Wechat) Pay() {
fmt.Println("Wechat Pay")
}
func (w Wechat) Talk() {
fmt.Println("Wechat Talk")
}
func (a AliPay) Pay() {
fmt.Println("AliPay Pay")
}
func (a AliPay) Talk() {
fmt.Println("AliPay Talk")
}
func main() {
var tool Tooler = AliPay{}
tool.Talk()
tool.Pay()
tool = Wechat{}
tool.Talk()
tool.Pay()
}
空接口
空接口是指没有定义任何方法的接口。因此任何类型都实现了空接口。
空接口类型的变量可以存储任意类型的变量。
package main
import "fmt"
func show(anything interface{}) {
fmt.Println(anything)
}
type Animal struct {
name string
age int
}
func main() {
show("fdsafdasf")
show(123)
show(Animal{
"neko",
12,
})
}
可以用any来替代
空接口还可以作为map的value值
package main
import "fmt"
func main() {
var studentInfo = make(map[string]interface{})
//var studentInfo = make(map[string]any)
studentInfo["name"] = "meowrain"
studentInfo["age"] = 12
studentInfo["hobby"] = "play computer"
fmt.Println(studentInfo)
}
类型断言
接口值
一个接口的值(简称接口值)是由一个具体类型和具体类型的值两部分组成的。这两部分分别称为接口的动态类型和动态值。
判断空接口中的这个值可以用类型断言
x.(T)
package main
import "fmt"
func show(anything interface{}) {
v, ok := anything.(string)
if ok {
fmt.Println(v)
} else {
fmt.Println("not string")
}
}
func main() {
show("fdsfdsafa")
show(23)
}