> 文档中心 > 【Go实战基础】多态是怎么实现的

【Go实战基础】多态是怎么实现的

目录

一、基本概念

二、数据结构

1、interface 定义接口

2、非空 interface 数据结构

3、空 interface 数据结构

三、菜鸟实战

1、创建 g006.go

2、编译和运行

3、运行结果


一、基本概念

面向对象编程(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 {sizeuintptr // 占用内存大小ptrdata    uintptr // 包含所有指针的内存前缀大小hashuint32  // 类型 hashtflag      tflag   // 标记位,用于反射align      uint8   // 对齐字节信息fieldAlign uint8   // 对齐字节数kinduint8   // 基础类型枚举值equal func(unsafe.Pointer, unsafe.Pointer) bool // 比较对应对象的类型是否相等gcdata    *byte    // GC 类型的数据strnameOff  // 类型名称字符串偏移量ptrToThis typeOff  // 类型元信息指针偏移量}

3、空 interface 数据结构

空的 inferface{} 是没有方法集的接口,所以不需要 itab 数据结构,只需要存类型和类型对应的值即可。对应的数据结构如下:

// 空接口定义// 只有当 2 个字段都为 nil,空接口才为 niltype eface struct {_type *_typedata  unsafe.Pointer}

空的 interface 没有方法,所以可以认为所有的类型都实现了 interface{}。
如果定义一个函数参数是 interface{} 类型,这个函数应该可以接受任何类型作为它的参数。

三、菜鸟实战

实战需求:定义并实现接口

马上安排!

1、创建 g006.go

/* * @Author: 菜鸟实战 * @FilePath: /go110/go-006/g006.go * @Description: 接口 */package mainimport ("fmt""runtime")// 定义结构体type Student struct {Name string}// 空接口func test_nil_interface() {var v interface{}v = 123v = "abcd"v = 10.2v = 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 
 

菜鸟实战,持续学习!