0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何实现implements ?

冬至子 来源:洋芋土豆 作者:真没什么深度 2023-05-22 17:30 次阅读

概述

Go 中检测一个类型是否实现了某个接口,通常分为两类机制: 编译期间运行期间

编译期间

顾名思义,编译期间检测就是通过静态分析来确定类型是否实现了某个接口,如果检测不通过,则编译过程报错并退出。通常将这种方式称为 接口完整性检查

接口完整性检查

类型未实现接口

package main

type Person interface {
    Name() string
    Age() int
}

type Martian struct {
}

func main() {
    // 强制类型 Martian 必须实现接口 Person 的所有方法
    var _ Person = (*Martian)(nil)

    // 1. 声明一个 _ 变量 (不使用)
    // 2. 把一个 nil 转换为 (*Martian),然后再转换为 Person
    // 3. 如果 Martian 没有实现 Person 的全部方法,则转换失败,编译器报错
}

运行代码

$ go run main.go
# 输出如下 
cannot use (*Martian)(nil) (value of type *Martian) as type Person in variable declaration:
        *Martian does not implement Person (missing Age method)

从输出的结果中可以看到,Martian 并没有实现 Person 接口,所以报错了。下面我们为 Martian 实现 Person 接口。

类型实现了接口

package main

import "fmt"

type Person interface {
    Name() string
    Age() int
}

type Martian struct {
}

// 实现 Name 方法
func (m *Martian) Name() string {
    return "martian"
}

// 实现 Age 方法
func (m *Martian) Age() int {
    return -1
}

func main() {
    // 此时 Martian 已实现了 Person 的全部方法
    var _ Person = (*Martian)(nil)

    m := &Martian{}
    fmt.Printf("name = %s, age = %d\\n", m.Name(), m.Age())
}

运行代码

$ go run main.go
# 输出如下 
name = martian, age = -1

从输出的结果中可以看到,运行成功,Martian 已经实现了 Person 接口的全部方法。

运行期间

运行期间的检测方式主要有 类型断言反射

类型断言

类型未实现接口

package main

import "fmt"

type Person interface {
    Name() string
    Age() int
}

type Martian struct {
}

func main() {
    // 变量必须声明为 interface 类型
    var m interface{}
    m = &Martian{}
    if v, ok := m.(Person); ok {
        fmt.Printf("name = %s, age = %d\\n", v.Name(), v.Age())
    } else {
        fmt.Println("Martian does not implements Person")
    }
}

运行代码

$ go run main.go
# 输出如下 
Martian does not implements Person

下面我们为 Martian 实现 Person 接口。

类型实现了接口

package main

import "fmt"

type Person interface {
    Name() string
    Age() int
}

type Martian struct {
}

func (m *Martian) Name() string {
    return "martian"
}

func (m *Martian) Age() int {
    return -1
}

func main() {
    // 变量必须声明为 interface 类型
    var m interface{}
    m = &Martian{}
    if v, ok := m.(Person); ok {
        fmt.Printf("name = %s, age = %d\\n", v.Name(), v.Age())
    }
}

运行代码

$ go run main.go
# 输出如下 
name = martian, age = -1

从输出的结果中可以看到,运行成功,Martian 已经实现了 Person 接口的全部方法。

反射

通过 reflect 包提供的 API 来判断类型是否实现了某个接口。

类型未实现接口

package main

import (
    "fmt"
    "reflect"
)

type Person interface {
    Name() string
    Age() int
}

type Martian struct {
}

func main() {
    // 获取 Person 类型
    p := reflect.TypeOf((*Person)(nil)).Elem()

    // 获取 Martian 结构体指针类型
    m := reflect.TypeOf(&Martian{})

    // 判断 Martian 结构体类型是否实现了 Person 接口
    fmt.Println(m.Implements(p))
}

运行代码

$ go run main.go
# 输出如下 
false

下面我们为 Martian 实现 Person 接口。

类型实现了接口

package main

import (
    "fmt"
    "reflect"
)

type Person interface {
    Name() string
    Age() int
}

type Martian struct {
}

func (m *Martian) Name() string {
    return "martian"
}

func (m *Martian) Age() int {
    return -1
}

func main() {
    // 获取 Person 类型
    p := reflect.TypeOf((*Person)(nil)).Elem()

    // 获取 Martian 结构体指针类型
    m := reflect.TypeOf(&Martian{})

    // 判断 Martian 结构体类型是否实现了 Person 接口
    fmt.Println(m.Implements(p))
}

运行代码

$ go run main.go
# 输出如下 
true

小结

Go 的接口实现检测机制分为 编译期间运行期间,其中编译期间的检测方式是 接口完整性检查, 而运行期间的检测方式有两种: 类型断言反射,一般情况尽量使用类型断言,这样可以避免反射带来的性能损耗。文中提到的几种检测方式的代码语法都比较新 (nan) 奇 (kan) ,读者可以参考代码的注释部分帮助理解。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • VaR
    VaR
    +关注

    关注

    0

    文章

    37

    浏览量

    11120
  • API接口
    +关注

    关注

    1

    文章

    79

    浏览量

    10315
  • go语言
    +关注

    关注

    1

    文章

    157

    浏览量

    8927
收藏 人收藏

    评论

    相关推荐

    150 面向对象接口 实现implements #硬声创作季

    编程程序代码
    充八万
    发布于 :2023年07月26日 02:36:18

    在三相电能测量系统实现电能质量分析的参考设计包括BOM及层图

    描述The TIDM-THDREADING reference design implements power quality analysis in a three-phase energy
    发表于 09-10 09:02

    基于LUT的输入处理的FPGA实现-应用笔记

    table (LUT). It implements a piecewise first-order linear approximation of a nonlinear function.
    发表于 09-14 21:32

    160MHz带宽标准无线信号测试仪的IF子系统包括BOM及层图

    描述This reference design implements an IF subsystem for a standard wireless signal tester
    发表于 09-18 09:05

    电压三倍器实现高输入至输出升压比的转换器参考设计

    描述This boost converter implements a voltage tripler which allows a high input-to-output boost
    发表于 09-19 09:14

    简易6LoWPAN网状终端节点参考设计包括BOM及层图

    描述This reference design implements a simple RF mesh network end node for smart meter Advanced
    发表于 10-26 10:07

    高带宽光学前端模块的实现方案含详细数据资料

    描述This reference design implements and measures a complete 120MHz wide bandwidth optical front end
    发表于 10-31 17:20

    实现两个小尺寸集成FET的8V-20V输入同步降压转换器

    描述The PMP11225 reference design implements two small-footprint integrated FET synchronous buck
    发表于 12-06 11:51

    dspic30f5011陷入未知状态

    嗨,AllI有一个非常困难的问题:(经过几天的正常工作,DSPIC30F5011卡在一个未知的状态。只有重置可以释放它。两个提示:1。SW实现16秒看门狗,在这个问题STATE2中似乎没有激活。SW
    发表于 05-07 12:26

    Lock体系结构和读写锁机制解析

    接口之一,规定了资源锁使用的几个基础方法。ReentrantLock类实现Lock接口的可重入锁,即线程如果获得当前实例的锁,并进入任务方法,在线程没有释放锁的状态下,可以再次进入任务方法,特点:互斥
    发表于 01-05 17:53

    #HarmonyOS征文#—HarmonyOS实现双击事件

    1. 双击事件双击事件和单击事件有些类似,也有四种实现的方法1.通过id找到组件。 2.给按钮组件设置双击事件。 3.本类实现DoubleClickedListener接口重写。 4.重写
    发表于 07-28 10:49

    HarmonyOS实战—实现长按事件

    实现案例:长按按钮修改文本内容新建项目:ListenerApplication3ability_main MainAbilitySlicepackage
    发表于 08-12 11:44

    android是怎样高仿华为充电动画

    public class BubbleViscosity extends SurfaceView implements SurfaceHolder.Callback, Runnable
    发表于 09-15 08:18

    分布式物模型开发实战过程

    实现// implements for generic onoff cli modelfunction model_sig_onoff() { // extends the model_base
    发表于 03-08 08:53

    使用AT89C2051微控制器实现简单温度计的设计

    The system presented in this application note implements a simple digital thermometerthat includes
    发表于 06-27 11:34 75次下载