golang中interface接口的深度解析

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日

相关文章

  • 自己动手写的javascript前端等待控件

    关于自己动手写的JavaScript前端等待控件,我将分几个方面进行讲解。 目的 在前端页面中,我们常常需要等待某个操作的完成,例如等待页面加载等待、等待AJAX数据、等待输入等操作,此时需要显示一个等待状态或者进度条等,来提示用户当前操作正在进行中。自己动手写一个前端等待控件,可以提高用户体验,让用户了解当前操作的状态。 基本思路 一个前端等待控件的基本思…

    other 2023年6月27日
    00
  • linuxbc命令

    linuxbc命令 bc是一个基础的计算器程序,基于GNU bison和GNU flex实现。它支持精度任意的浮点计算和整数计算,可以进行高度精确的数学运算。bc命令通常可以在标准命令行终端中运行,也可以用来编写包含复杂数学表达式的脚本。 基本用法 bc命令的基本使用方法为: $ bc 上述命令将进入bc计算器交互模式。在该模式下,每一个输入行将会被认为是一…

    其他 2023年3月28日
    00
  • 在vue项目中引入scss并使用scss样式详解

    在Vue项目中引入SCSS并使用SCSS样式详解 在Vue项目中,我们可以使用SCSS(Sass)来编写样式,并通过引入SCSS文件来使用这些样式。下面是在Vue项目中引入SCSS并使用SCSS样式的完整攻略。 步骤一:安装依赖 首先,我们需要安装相关的依赖。在Vue项目的根目录下,打开终端并执行以下命令: npm install sass-loader n…

    other 2023年7月29日
    00
  • 详解git基本操作和指令

    详解Git基本操作和指令攻略 Git是一种分布式版本控制系统,用于跟踪文件的变化并协同开发。本攻略将详细介绍Git的基本操作和指令,帮助您快速上手使用Git。 1. 初始化Git仓库 在开始使用Git之前,需要先初始化一个Git仓库。可以通过以下命令在当前目录下初始化一个新的Git仓库: git init 2. 添加和提交文件 在Git中,需要将文件添加到暂…

    other 2023年8月3日
    00
  • C++枚举类型enum与enum class的使用

    C++枚举类型enum与enum class的使用攻略 枚举类型是C++中一种用于定义命名常量的数据类型。它允许我们为一组相关的常量赋予有意义的名称,提高代码的可读性和可维护性。C++中有两种枚举类型:enum和enum class。本攻略将详细讲解它们的使用。 enum类型 enum类型是C++中最早引入的枚举类型,它的语法相对简单。下面是enum类型的基…

    other 2023年8月20日
    00
  • 想要安装win7 64位系统该怎么配置台式机电脑?

    安装Windows 7 64位系统需要确保你的台式机电脑满足一些最低配置要求。以下是一个完整的攻略,包含了安装Windows 7 64位系统的步骤以及两个示例说明。 配置要求 在安装Windows 7 64位系统之前,请确保你的台式机电脑满足以下最低配置要求: 处理器:64位处理器,至少为1 GHz的速度 内存:至少4 GB的RAM 存储空间:至少20 GB…

    other 2023年8月2日
    00
  • ftp使用

    FTP使用 FTP,即File Transfer Protocol,是指一种用于文件传输的协议,是互联网上使用最广泛、应用最为广泛的文件传输协议之一。它可以用来将文件从本地计算机上传到远程服务器或者将服务器上的文件下载到本地计算机中。 本文将介绍如何使用FTP进行文件传输。 FTP客户端软件的安装 在使用FTP进行文件传输之前,需要先安装FTP客户端软件。目…

    其他 2023年3月28日
    00
  • C语言 指针与数组的详解及区别

    C语言 指针与数组的详解及区别 在 C 语言中,指针和数组是两个重要的概念,尤其在涉及到复杂数据类型(比如字符串、结构体等)的操作时,它们更是无可替代。本文将详细讲解指针和数组的概念、用法及区别,希望对初学者有所帮助。 指针的概念及用法 指针可以理解为存储内存地址的变量,它可以指向任何数据类型(包括其他指针)。在 C 语言中,我们可以通过“&”符号来…

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