目录
一、基本概念
面向对象编程(OOP)中三个基本特征分别是封装,继承,多态。在 Go 语言中封装和继承是通过 struct 来实现的,而多态则是通过接口(interface)来实现的。
Interface 是 Go 语言的基础特性之一,可以理解为一种类型的规范或者约定。 在 Go 中,接口是一组方法签名。当类型为接口中的所有方法提供定义时,它被称为实现接口。
当我们给系统添加一个功能的时候,不是通过修改代码,而是通过增添代码来完成,那么就是开闭原则的核心思想了。要想满足这种要求,就需要interface来提供一层抽象的接口,从而实现高内聚,低耦合。
二、数据结构
1、interface 定义接口
使用关键字 interface 用来定义接口,语法如下:
// 定义一个接口
type interface_name interface {
method_name1([args ...arg_type]) [return_type]
method_name2([args ...arg_type]) [return_type]
method_name3([args ...arg_type]) [return_type]
...
method_namen([args ...arg_type]) [return_type]
}
2、非空 interface 数据结构
非空的 interface 初始化的底层数据结构是 iface
// 非空 interface 数据结构
type iface struct {
// 存放类型、方法等信息,是 itab 类型的指针
tab *itab
// 指向的 iface 绑定对象的原始数据的副本
data unsafe.Pointer
}
// itab 指针数据结构
type itab struct {
// 存 interface 自己的静态类型
inter *interfacetype
// 类型元信息,存 interface 对应具体对象的类型
_type *_type
// hash 字段
hash uint32
_ [4]byte
// 函数指针,它指向的是具体类型的函数方法
// 在这个指针对应内存地址的后面依次存储了多个方法,利用指针偏移便可以找到它们
fun [1]uintptr
}
Go 语言在编译时会对每个变量的类型信息做强校验,所以每个类型的元信息要用一个结构体描述,_type 就是所有类型最原始的元信息。
// 类型元信息
type _type struct {
size uintptr // 占用内存大小
ptrdata uintptr // 包含所有指针的内存前缀大小
hash uint32 // 类型 hash
tflag tflag // 标记位,用于反射
align uint8 // 对齐字节信息
fieldAlign uint8 // 对齐字节数
kind uint8 // 基础类型枚举值
equal func(unsafe.Pointer, unsafe.Pointer) bool // 比较对应对象的类型是否相等
gcdata *byte // GC 类型的数据
str nameOff // 类型名称字符串偏移量
ptrToThis typeOff // 类型元信息指针偏移量
}
3、空 interface 数据结构
空的 inferface{} 是没有方法集的接口,所以不需要 itab 数据结构,只需要存类型和类型对应的值即可。对应的数据结构如下:
// 空接口定义
// 只有当 2 个字段都为 nil,空接口才为 nil
type eface struct {
_type *_type
data unsafe.Pointer
}
空的 interface 没有方法,所以可以认为所有的类型都实现了 interface{}。
如果定义一个函数参数是 interface{} 类型,这个函数应该可以接受任何类型作为它的参数。
三、菜鸟实战
实战需求:定义并实现接口
马上安排!
1、创建 g006.go
/*
* @Author: 菜鸟实战
* @FilePath: /go110/go-006/g006.go
* @Description: 接口
*/
package main
import (
"fmt"
"runtime"
)
// 定义结构体
type Student struct {
Name string
}
// 空接口
func test_nil_interface() {
var v interface{}
v = 123
v = "abcd"
v = 10.2
v = Student{Name: "Tom"} // 自定义结构体类型
//判断v的类型
if _, ok := v.(int); ok {
fmt.Printf(" 是int类型 \n")
} else if _, ok := v.(string); ok {
fmt.Printf(" 是字符串类型\n")
} else if _, ok := v.(Student); ok {
fmt.Printf(" 是自定义结构体类型\n")
} else {
fmt.Printf("未知类型\n")
}
}
// 定义接口
type Phone interface {
call()
sendMessage()
}
// 声明结构体, 实现接口
type Huawei struct {
name string
}
// Huawei 实现接口
func (huawei Huawei) call() {
fmt.Printf("%s 有打电话功能...\n", huawei.name)
}
func (huawei Huawei) sendMessage() {
fmt.Printf("%s 有发短信功能...\n", huawei.name)
}
func test_interface() {
// 华为
mate := Huawei{
name: "Mate",
}
mate.call()
mate.sendMessage()
}
func main() {
// 使用内置函数打印
println("Hello", "菜鸟实战")
// 测试 空接口
test_nil_interface()
// 测试 非空接口
test_interface()
// 使用包函数打印
fmt.Printf("版本: %s \n", runtime.Version())
}
2、编译和运行
# 1、生成模块依赖
go mod init g006
# 2、编译
go build g006.go
# 3、编译后的目录结构
└── go-006
├── g006
├── g006.go
└── go.mod
# 4、运行
go run g006
3、运行结果
Hello 菜鸟实战
是自定义结构体类型
Mate 有打电话功能...
Mate 有发短信功能...
版本: go1.17.10
菜鸟实战,持续学习!