golang学习笔记——接口interfaces

news2024/11/19 8:39:47

文章目录

  • Go 语言接口
  • 例子
  • 空接口
    • 空接口的定义
    • 空接口的应用
      • 空接口作为函数的参数
      • 空接口作为map的值
  • 类型断言
    • 接口值
  • 类型断言例子001
  • 类型断言例子002
  • 类型断言例子003
  • 巩固练习

Go 语言接口

接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节。
interface是一组method的集合,是duck-type programming的一种体现。接口做的事情就像是定义一个协议(规则),只要一台机器有洗衣服和甩干的功能,我就称它为洗衣机。不关心属性(数据),只关心行为(方法)。

为了保护你的Go语言职业生涯,请牢记接口(interface)是一种类型。

interface类型可以定义一组方法,但是不需要实现。并且接口(interface)不能包含任何变量

在这里插入图片描述
实例

/* 定义接口 */
type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

/* 定义结构体 */
type struct_name struct {
   /* variables */
}

/* 实现接口方法 */
func (struct_name_variable struct_name) method_name1() [return_type] {
   /* 方法实现 */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
   /* 方法实现*/
}

例子

Go 中的接口是满足隐式实现的(这一点是非常坑人的,建议阅读 Go语言令人厌恶的设计)。 Go 不提供用于实现接口的关键字。

package main

import (
    "fmt"
	"math"
)


func main() {
    var s Shape = Square{3}
    printInformation(s)

    c := Circle{6}
    printInformation(c)
}

//打印面积和周长
func printInformation(s Shape) {
    fmt.Printf("%T\n", s)
    fmt.Println("Area: ", s.Area())
    fmt.Println("Perimeter:", s.Perimeter())
    fmt.Println()
}

//---Shape 形状---
type Shape interface {
	//周长
    Perimeter() float64
    //面积
    Area() float64
}

//---Square 正方形---
type Square struct {
    size float64
}

func (s Square) Area() float64 {
    return s.size * s.size
}

func (s Square) Perimeter() float64 {
    return s.size * 4
}

//---Circle 圆形---
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
}

输出

main.Square
Area:  9
Perimeter: 12

main.Circle
Area:  113.0973
Perimeter: 37.6991

空接口

空接口的定义

空接口是指没有定义任何方法的接口。因此任何类型都实现了空接口。

空接口类型的变量可以存储任意类型的变量。

func main() {
    // 定义一个空接口x
    var x interface{}
    s := "pprof.cn"
    x = s
    fmt.Printf("type:%T value:%v\n", x, x)
    i := 100
    x = i
    fmt.Printf("type:%T value:%v\n", x, x)
    b := true
    x = b
    fmt.Printf("type:%T value:%v\n", x, x)
}

空接口的应用

空接口作为函数的参数

使用空接口实现可以接收任意类型的函数参数。

// 空接口作为函数参数
func show(a interface{}) {
    fmt.Printf("type:%T value:%v\n", a, a)
} 

空接口作为map的值

使用空接口实现可以保存任意值的字典。

// 空接口作为map值
    var studentInfo = make(map[string]interface{})
    studentInfo["name"] = "李白"
    studentInfo["age"] = 18
    studentInfo["married"] = false
    fmt.Println(studentInfo) 

类型断言

空接口可以存储任意类型的值,那我们如何获取其存储的具体数据呢?

接口值

一个接口的值(简称接口值)是由一个具体类型和具体类型的值两部分组成的。这两部分分别称为接口的动态类型和动态值。

我们来看一个具体的例子:

var w io.Writer
w = os.Stdout
w = new(bytes.Buffer)
w = nil 

请看下图分解:
在这里插入图片描述
想要判断空接口中的值这个时候就可以使用类型断言,其语法格式:

    x.(T) 

其中:

    x:表示类型为interface{}的变量
    T:表示断言x可能是的类型。

该语法返回两个参数,第一个参数是x转化为T类型后的变量,第二个值是一个布尔值,若为true则表示断言成功,为false则表示断言失败。

举个例子:

func main() {
    var x interface{}
    x = "pprof.cn"
    v, ok := x.(string)
    if ok {
        fmt.Println(v)
    } else {
        fmt.Println("类型断言失败")
    }
} 

上面的示例中如果要断言多次就需要写多个if判断,这个时候我们可以使用switch语句来实现:

func justifyType(x interface{}) {
    switch v := x.(type) {
    case string:
        fmt.Printf("x is a string,value is %v\n", v)
    case int:
        fmt.Printf("x is a int is %v\n", v)
    case bool:
        fmt.Printf("x is a bool is %v\n", v)
    default:
        fmt.Println("unsupport type!")
    }
} 

因为空接口可以存储任意类型值的特点,所以空接口在Go语言中的使用十分广泛。

关于接口需要注意的是,只有当有两个或两个以上的具体类型必须以相同的方式进行处理时才需要定义接口。不要为了接口而写接口,那样只会增加不必要的抽象,导致不必要的运行时损耗。

类型断言例子001

类型断言也可以判断指针类型

package main

import "fmt"

func main() {

	var n1 int32 = 30
	var n2 string = "tomcat"
	n3 := false

	stu1 := Student{}
	stu2 := &Student{}

	justifyType(n1,n2,n3,stu1,stu2)
}


type Student struct {

}

func justifyType(items ...interface{}) {
	for index, x := range items {
		switch v := x.(type) {
		case string:
			fmt.Printf("第%v个参数是 string 类型,值是 %v\n",index,v)
		case int:
			fmt.Printf("第%v个参数是 int 类型,值是 %v\n",index,v)
		case bool:
			fmt.Printf("第%v个参数是 bool 类型,值是 %v\n",index,v)
		case Student:
			fmt.Printf("第%v个参数是 Student 类型,值是 %v\n",index,v)
		case *Student:
			fmt.Printf("第%v个参数是 *Student 类型,值是 %v\n",index,v)
		default:
			fmt.Println("unsupport type!")
		}
	}
} 

类型断言例子002

package main

import "fmt"

func main() {
    var i interface{} = "Hello, World"
    str, ok := i.(string)
    if ok {
        fmt.Printf("'%s' is a string\n", str)
    } else {
        fmt.Println("conversion failed")
    }
}

类型断言例子003

给Phone结构体一个特有的方法Call(),当Usb接口接收的是Phone变量时,还需要调用call方法

package main

import "fmt"


func main() {
    //定义一个usb接口数组,可以存放Phone和Camera的结构体变量
	// 这里就体现出多态数组
	var usbArr [3]Usb
	usbArr[0] = Phone{"vivo"}
	usbArr[1] = Phone{"小米"}
	usbArr[2] = Camera{"惠普"}

	//遍历usbArr
	var computer Computer
	for _, v := range usbArr {
		computer.Working(v)
	}
}


type Usb interface {
	Start()
	Stop()
}

type Camera struct {
	name string		
}

type Phone struct {
	name string
}

type Computer struct {
	name string
}

func (c Camera) Start() {
	fmt.Println("相机开始工作...")
}

func (c Camera) Stop() {
	fmt.Println("相机停止工作...")
}

func (p Phone) Start() {
	fmt.Printf("%s 手机开始工作...\n", p.name )
}

func (p Phone) Stop() {
	fmt.Printf("%s 手机停止工作...\n", p.name )
}

func (p Phone) Call() {
	fmt.Println("手机 打电话")
}

func (computer Computer) Working(usb Usb) {
	usb.Start()
	if phone, ok := usb.(Phone); ok {
		phone.Call()
	}
	usb.Stop()
}

巩固练习

  1. 在Go语言中,接口是什么?请解释其含义。
  2. 如何定义一个接口?解释接口定义的基本语法。
  3. Go语言中的接口实现是如何工作的?请详细解释。
  4. 什么是空接口?它有什么用途?
  5. 能否给出一些使用接口的例子?这些例子中接口的作用是什么?
  6. Go语言不同接口、声明了同名方法,怎么解决问题?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1225999.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

对象与this

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 最近想再聊聊Java的对象…

vscode pandas无法使用

一、代码内容 import csv csv_reader csv.reader(open("data.csv")) for row in csv_reader:print(row) print(row[2]) 二、错误提示 ModuleNotFoundError: No module named pandas 三、安装pandas 然后我安装pandas,因为我的python的版本是python …

C++类与对象(1)—初步认识

目录 一、面向过程和面向对象 二、类 1、定义 2、类的两种定义方式 3、访问限定符 4、命名规范化 5、类的实例化 6、计算类对象的大小 7、存储方式 三、this指针 1、定义 2、存储位置 3、辨析 四、封装好处 一、面向过程和面向对象 C语言是面向过程的&#xf…

新版mmdetection3d将3D bbox绘制到图像

环境信息 使用 python mmdet3d/utils/collect_env.py收集环境信息 sys.platform: linux Python: 3.7.12 | packaged by conda-forge | (default, Oct 26 2021, 06:08:21) [GCC 9.4.0] CUDA available: True numpy_random_seed: 2147483648 GPU 0,1: NVIDIA GeForce RTX 3090 …

11月19日

一、选择题1.一般认为,世界上第1台电子数字计算机诞生于()年。 A. 1946 B. 1952 C. 1959 D. 1962 1946 记:4 5 6 7 8 平均十年一代 一、计算机发展五代1946年, 世界上第一台数字电子计算机ENIAC 1.1946年开始,第一代电子管计算机…

<Linux>权限管理|权限分类|权限设置|权限掩码|粘滞位

文章目录 Linux权限的概念Linux权限管理a. 文件访问者的分类b. 文件类型和访问权限c. 文件权限表示方法d. 文件权限的设置权限掩码file指令粘滞位 权限总结权限作业 Linux权限的概念 Linux下有两种用户:超级用户(root)和普通用户。 超级用户:可以在Lin…

Python操作Excel常用方法汇总

目录 引言 一、使用pandas库操作Excel 1、读取Excel文件 2、写入Excel文件 3、处理Excel数据 二、使用openpyxl库操作Excel 1、读取Excel文件 2、写入Excel文件 3、处理Excel数据 三、高级功能 总结 引言 Python是一种功能强大的编程语言,它可以用来处理…

MongoDB相关基础操作(库、集合、文档)

文章目录 一、库的相关操作1、查看数据库2、查看当前库3、创建数据库4、删除数据库 二、集合的相关操作1、查看库中所有集合2、创建集合2.1、显示创建2.2、隐式创建 3、删除集合 三、文档的相关操作1、插入文档1.1、插入单条文档1.2、插入多条文档1.3、脚本方式 2、查询文档3、…

电商平台革新:食派士小程序的无代码开发与广告推广集成

食派士小程序:无代码开发的连接神器 食派士小程序,作为上海食派士商贸发展有限公司的专利产品,是一种凭借无代码开发,就能实现与各种系统的连接和集成的电商解决方案。它采用无代码开发的方式,避免了API开发的复杂过程…

原型网络Prototypical Network的python代码逐行解释,新手小白也可学会!!-----系列8

文章目录 前言一、原始代码二、对每一行代码的解释:总结 前言 这是该系列原型网络的最后一段代码及其详细解释,感谢各位的阅读! 一、原始代码 if __name__ __main__:##载入数据labels_trainData, labels_testData load_data() # labels_…

常见树种(贵州省):001松类

摘要:本专栏树种介绍图片来源于PPBC中国植物图像库(下附网址),本文整理仅做交流学习使用,同时便于查找,如有侵权请联系删除。 图片网址:PPBC中国植物图像库——最大的植物分类图片库 一、华山松…

麻将馆电脑计费系统,棋牌室怎么用电脑控制灯计时,佳易王计时计费系统软件下载

麻将馆电脑计费系统,棋牌室怎么用电脑控制灯计时,佳易王计时计费系统软件下 棋牌室电脑灯控系统,需要安装一个灯控器,软件发出开灯和关灯的指令,相应的灯就打开或关闭。在点击开始计时的时候,开灯&#xff…

黔院长 | 为什么要调经络?原来通经络对人体健康如此重要!

人体的组成较为复杂,在外有皮肤、毛发;在内有经络、五脏;其他还有我们看不到的精气、津液等等,也因此人体会生各种各样的疾病。 为什么说经络畅通对人体健康如此重要?身体内外始终是一个统一的整体,内外之间…

vue3基础学习

##以前怎么玩的? ###MVC Model:Bean View:视图 Controller ##vue的ref reactive ref:必须是简单类型 reactive:必须不能是简单类型 ###创建一个Vue项目 npm init vuelatest ###生命周期 ###setup相关 ####Vue2的一些写法 -- options API ####Vue3的写法 组合式API Vu…

Python —— Mock接口测试

前言 今天跟小伙伴们一起来学习一下如何编写Python脚本进行mock测试。 什么是mock? 测试桩,模拟被测对象的返回,用于测试 通常意义的mock指的就是mock server, 模拟服务端返回的接口数据,用于前端开发,第三方接口联调 为什么…

数据结构与算法-哈夫曼树与图

🌞 “永远积极向上,永远豪情满怀,永远热泪盈眶!” 哈夫曼树与图 🎈1.哈夫曼树🔭1.1树与二叉树的转换🔭1.2森林与二叉树的转换🔭1.3哈夫曼树🔎1.3.1哈夫曼树的概念&#x…

大数据HCIE成神之路之数学(2)——线性代数

线性代数 1.1 线性代数内容介绍1.1.1 线性代数介绍1.1.2 代码实现介绍 1.2 线性代数实现1.2.1 reshape运算1.2.2 转置实现1.2.3 矩阵乘法实现1.2.4 矩阵对应运算1.2.5 逆矩阵实现1.2.6 特征值与特征向量1.2.7 求行列式1.2.8 奇异值分解实现1.2.9 线性方程组求解 1.1 线性代数内…

基于STM32单片机数字电压表自动切换量程及源程序

一、系统方案 1、本设计采用这STM32单片机作为主控器。 2、液晶1602显示。 3、内部ADC采集电压0-12V,自动切换档位。 二、硬件设计 原理图如下: 三、单片机软件设计 1、首先是系统初始化 u8 i; u16 a,b,c,d; u16 adcx; float adc; unsigned char datas…

AIGC实战 - 使用变分自编码器生成面部图像

AIGC实战 - 使用变分自编码器生成面部图像 0. 前言1. 数据集分析2. 训练变分自编码器2.1 变分自编码器架构2.2 变分自编码器分析 3. 生成新的面部图像4. 潜空间算术5. 人脸变换小结系列链接 0. 前言 在自编码器和变分自编码器上,我们都仅使用具有两个维度的潜空间。…

Alien Skin Exposure2024免费版图片颜色滤镜插件

Alien Skin Exposure一款非常专业的图片后期处理软件,内含500多种照片滤镜。是一款图片后期处理功能非常强大的软件。这款软件可以对图片的后期效果做很好的处理。 打开Alien Skin Exposure软件,会显示下面这个界面,如图1. ExposureX8win-安…