golang中interface接口的深度解析

yizhihongxing

Golang中Interface接口的深度解析

理解Interface接口

在Golang中,interface被称作为接口,它定义了一种方法集合,但是实现这些方法的具体结构并不在定义时确定,而是在后续具体实现时确定。interface实现了Java、C#等语言中接口的概念,但是与其他语言中的接口不同的是,Golang的interface是隐式实现(implicit),即不需要显式地声明该结构体类型实现了某个接口。

一个interface的定义如下:

type Shape interface {
    Area() float64
    Perimeter() float64
}

以上代码定义了一个Shape接口,其中Area()和Perimeter()分别是该接口的两个方法。其他结构体可以通过实现Area()和Perimeter()方法来实现该接口。

接口还可以嵌套,例如:

type Shape interface {
    Area() float64
    Perimeter() float64
}

type HasColor interface {
    GetColor() string
}

type ColoredShape interface {
    Shape
    HasColor
}

以上代码定义了一个ColoredShape接口,它嵌套了Shape和HasColor两个接口,其中Shape和HasColor的方法都可以被ColoredShape继承。

接口的具体实现

接口的具体实现要求实现该接口中定义的所有方法。例如,以下代码定义了一个Rect矩形结构体,并实现了Shape接口中定义的Area()和Perimeter()方法:

type Rect struct {
    Width  float64
    Height float64
}

func (r Rect) Area() float64 {
    return r.Width * r.Height
}

func (r Rect) Perimeter() float64 {
    return 2 * (r.Width + r.Height)
}

以上代码定义了一个Rect矩形结构体,并实现了Area()和Perimeter()方法。由于该方法集符合Shape接口的方法集,因此Rect结构体就隐式实现了Shape接口。

接口的类型断言

接口类型可以赋值为结构体类型(或其他实现该接口的数据类型),反之亦然。

当我们需要确定接口类型具体是哪个结构体类型时,需要用到类型断言(type assertion)。

var s Shape = Rect{Width: 10, Height: 20}
r, ok := s.(Rect)
if ok {
    fmt.Println(r.Width, r.Height)
}

以上代码定义了一个Shape接口类型的s变量,并将其赋值为Rect{Width: 10, Height: 20},接着进行了类型断言,判断变量s是否是Rect类型,如果是则进行输出。注意,类型断言的第二个返回值ok为bool类型,表示类型断言是否成功。

接口的空接口

在Golang中,所有类型都实现了一个空接口(interface{}),因为空接口不包含任何方法,所以所有类型都与空接口“匹配”,也就是说可以将任何类型的值赋值给空接口变量,例如:

var i interface{}
i = 42
i = "hello, world"
i = Rect{Width: 10, Height: 20}

以上代码演示了将int、string以及Rect结构体类型分别赋值给空接口变量的过程。

接口常见问题及解答

接口的性能问题

在Golang中,接口定义和实现仅仅涉及到包装器和虚拟函数表的使用。这种“使用方式”不会使代码的性能受到负面影响。

接口和类型的关系

在Golang中,接口运作与类型的概念具有某些相似之处。接口表现为“约束”,并且可以隐式转换为不同的类型。这与类型无关,也就是说,接口不是类型。

接口的实际应用是什么?

接口主要用于两个方面:

  1. 表示包装和操作某个功能集的“契约协议”,而不是某个具体实现。
  2. 当一个值需要在多个实现之间进行交互时,该值的接口通常用作与他人交互的“平台”。这种交互可能是基于契约规定的。接口可以让多个实现统一分配,并且降低编译时关联和编译时的静态性。因此,接口可以在代码的不同部分引用并使用,而不需要,针对每种情况进行特定的构建。

示例

下面的示例展示了如何使用接口来表示和操作不同类型的几何形状。

package main

import (
    "fmt"
    "math"
)

type Shape interface {
    Area() float64
    Perimeter() float64
}

type Rectangle struct {
    Width  float64
    Height float64
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func (r Rectangle) Perimeter() float64 {
    return 2 * (r.Width + r.Height)
}

type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
    return 2 * math.Pi * c.Radius
}

func ShowShapeInfo(shape Shape) {
    fmt.Printf("Shape type: %T, Area: %f, Perimeter: %f\n", shape, shape.Area(), shape.Perimeter())
}

func main() {
    rect := Rectangle{Width: 10, Height: 20}
    circle := Circle{Radius: 5}

    ShowShapeInfo(rect)
    ShowShapeInfo(circle)
}

输出结果如下:

Shape type: main.Rectangle, Area: 200.000000, Perimeter: 60.000000
Shape type: main.Circle, Area: 78.539816, Perimeter: 31.415927

以上代码定义了Shape接口,然后在Rectangle和Circle两个结构体中实现了Area()和Perimeter()方法,并在ShowShapeInfo函数中传入Shape接口类型的参数,最终输出该参数的Area()和Perimeter()方法的结果。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:golang中interface接口的深度解析 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • C/C++实现投骰子游戏

    首先,我们需要确定投骰子游戏的规则和逻辑。 投骰子游戏通常由两个及以上玩家进行,每个玩家轮流投掷骰子,将骰子点数相加计算得分,总分数高者获胜。在每次投掷后,玩家可以选择停止投掷并计算得分,也可以继续投掷骰子。如果在投掷过程中出现了骰子点数之和等于7的情况,本轮该玩家得分清零。 基于这个规则,我们可以开始进行C/C++实现投骰子游戏的编写。 定义骰子点数范围和…

    other 2023年6月26日
    00
  • centos安装pip的方法总结

    当然,我很乐意为您提供有关“CentOS安装pip的方法总结”的完整攻略。以下是详细的步骤和两个示例: 1. 什么是pip? pip是Python的包管理器,用于安装和管理Python包。它可以自动解决依赖关系,并从Python Package Index(PyPI)下载和安装Python包。 2. CentOS安装pip 以下是在CentOS上安装pip的…

    other 2023年5月6日
    00
  • win2003分布式文件系统(dfs)配置方法[图文详解]

    Win2003 分布式文件系统(DFS)配置方法 DFS是分布式文件系统的缩写,它是微软提出的一种公用文件系统,可以通过不同的物理位置和不同的协议将文件映射到网络上的许多不同位置。同时,它通过名字空间机制,使多个服务器共享的文件目录树具有唯一的网络路径名。 下面我们详细介绍 Win2003 分布式文件系统(DFS)的配置方法。 步骤 1:安装分布式文件系统(…

    other 2023年6月27日
    00
  • Android APP检测实体按键事件详解

    Android APP检测实体按键事件详解攻略 在Android应用程序中,检测实体按键事件是一项重要的功能。通过捕捉用户在设备上按下、释放或长按的按键事件,我们可以实现各种交互和功能。下面是一个详细的攻略,介绍如何在Android应用程序中检测实体按键事件。 步骤1:创建一个新的Android项目 首先,我们需要创建一个新的Android项目。可以使用An…

    other 2023年9月6日
    00
  • 关于工伤事故索赔计算很好用的一款APP

    关于工伤事故索赔计算很好用的一款APP 如果您是一名企业主或员工,工伤事故索赔可能是您关注的一个重要问题。在处理工伤索赔时,听说有一款名为工伤事故索赔计算的APP非常有用,那么它有哪些特点呢? 功能介绍 这款工伤事故索赔计算APP的主要功能如下: 帮助用户计算工伤事故索赔赔偿额度 根据不同类型的工伤事故,提供不同的计算公式 提供现行相关法律法规的查询服务 支…

    其他 2023年3月28日
    00
  • 处理Shell脚本中带有空格的变量(bash脚本)

    当处理Shell脚本中带有空格的变量时,我们需要注意一些细节。下面是一个完整的攻略,包含了两个示例说明。 示例1:使用双引号引用变量 在Shell脚本中,我们可以使用双引号来引用带有空格的变量。这样可以确保变量的值被当作一个整体来处理。以下是一个示例: #!/bin/bash name=\"John Doe\" echo \"H…

    other 2023年8月16日
    00
  • win7鼠标右键菜单屏幕上有残影怎么办?

    Win7鼠标右键菜单屏幕上有残影怎么办? 如果您在使用Windows 7 操作系统时,经常出现右键单击时出现菜单后在屏幕上留下残影的情况,可能会影响您的使用体验。下面是一些解决方法以及可能导致这种情况的原因。 解决方法 重新启动Windows Explorer 尝试重新启动Windows Explorer进程可能会解决屏幕上残影的问题。您可以使用以下步骤来重…

    other 2023年6月27日
    00
  • Three.js学习之文字形状及自定义形状

    下面给您详细讲解“Three.js学习之文字形状及自定义形状”的完整攻略。 一、文字形状 Three.js中可以使用字体创建文字,并将文字转换为3D形状,以便在3D场景中使用。下面的代码片段演示了如何使用字体创建一个文字对象: import * as THREE from ‘three’; import { FontLoader } from ‘three/…

    other 2023年6月26日
    00
合作推广
合作推广
分享本页
返回顶部