【Go语言】接口类型(一)接口类型与接口的值

server/2024/9/25 8:04:39/

本文是介绍golang接口类型的第一篇,主要介绍接口类型与接口类型的值的相关概念。

1. 静态类型、动态类型、动态值

所谓的静态类型(即 static type),就是变量声明的时候的类型。

var age int   // int 是静态类型
var name string  // string 也是静态类型

它是你在编码时,肉眼可见的类型。
所谓的 动态类型(即 concrete type,也叫具体类型)是 程序运行时系统才能看见的类型。
这是什么意思呢?
我们都知道 空接口 可以承接什么问题类型的值,什么 int 呀,string 呀,都可以接收。
比如下面这几行代码

var i interface{}   
i = 18  
i = "Go编程"

第一行:我们在给 i 声明了 interface{} 类型,所以 i 的静态类型就是 interface{}
第二行:当我们给变量 i 赋一个 int 类型的值时,它的静态类型还是 interface{},这是不会变的,但是它的动态类型此时变成了 int 类型。
第三行:当我们给变量 i 赋一个 string 类型的值时,它的静态类型还是 interface{},它还是不会变,但是它的动态类型此时又变成了 string 类型。
从以上,可以知道,不管是 i=18 ,还是 i=“Go编程”,都是当程序运行到这里时,变量的类型,才发生了改变,这就是我们最开始所说的动态类型是程序运行时系统才能看见的类型

2. 接口类型的值

由于接口类型的值可以是任意一个实现该接口的类型值,所以除了具体的值,接口值还需要记录这个值的类型。也就是说接口值由类型(type)和值(value)组成。鉴于这两部分会根据存入的值不同而发送变化,我们称之为接口的动态类型动态值

type Mover interface {Move()
}type Dog struct {Name string 
}func (d *Dog) Move() {fmt.Println("狗在跑")
}type Car struct {Brand string
}func (c *Car) Move() {fmt.Println("汽车在跑")
}
var m Mover

image.png

fmt.Println(m==nil)  // true

此时将一个*Dog结构体赋值给m

m = &Dog{Name : "旺财"}

image.png
为接口变量m赋值一个*Car类型的值

m = new(Car)

image.png

fmt.Println(m==nil)  //false

此时仅仅是动态值是nil,动态类型不是nil,所以m不等于nil
接口值支持比较,当且仅当接口值的动态类型和动态值相等时相等

var (x Mover = new(Dog)y Mover = new(Car)
)fmt.Println(x==y)   // false

Go 语言中,interface 的内部实现包含了 2 个字段,类型 T 和 值 V,interface 可以使用 == 或 != 比较。2 个 interface 相等有以下 2 种情况

  1. 两个 interface 均等于 nil(此时 V 和 T 都处于 unset 状态)
  2. 类型 T 相同,且对应的值 V 相等。

看下面的例子:

type Stu struct {Name string
}type StuInt interface{}func main() {var stu1, stu2 StuInt = &Stu{"Tom"}, &Stu{"Tom"}var stu3, stu4 StuInt = Stu{"Tom"}, Stu{"Tom"}fmt.Println(stu1 == stu2) // falsefmt.Println(stu3 == stu4) // true
}

stu1 和 stu2 对应的类型是 *Stu,值是 Stu 结构体的地址,两个地址不同,因此结果为 false。
stu3 和 stu4 对应的类型是 Stu,值是 Stu 结构体,且各字段相等,因此结果为 true。

总结

  1. 接口类型的值包含动态类型和动态值。
  2. 接口类型的变量支持相互比较,只有当两个变量的动态类型和动态值都相等时两者才相等。
  3. 接口类型的变量支持和nil比较,只有当动态类型和动态值都为nil的时候两者才相等。

http://www.ppmy.cn/server/16644.html

相关文章

Vuforia AR篇(三)— AR模型出场效果

目录 前言一、AR模型出场二、AR出场特效三、添加过渡效果四、效果 前言 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。 一、AR模型出场 创建ARCamer…

「案例分享」DevExpress XAF (WinForms UI)赋能医疗管理系统,让操作更自动化!

DevExpress XAF是一款强大的现代应用程序框架,它采用模块化设计,开发人员可以选择内建模块,也可以自行创建,从而以更快的速度和比开发人员当前更强有力的方式创建应用程序。 获取DevExpress 新版正式版下载(Q技术交流&#xff1a…

Spring Boot集成Redisson实现延迟队列

项目场景: 在电商、支付等领域,往往会有这样的场景,用户下单后放弃支付了,那这笔订单会在指定的时间段后进行关闭操作,细心的你一定发现了像某宝、某东都有这样的逻辑,而且时间很准确,误差在1s内…

C++之AVL树的使用以及原理详解

1.AVL树 1.1AVL树的概念 1.2AVL树的定义 1.3AVL树的插入 1.4AVL树的旋转 1. 右单旋 2. 左单旋 3. 左右双旋 4. 右左双旋 1.5AVL树的验证 1.6AVL的实现 在之前对map/multimap/set/multiset进行了简单的介绍(C之map_set的使用-CSDN博客),…

【计算机网络】成功解决 ARP项添加失败:请求的操作需要提升

最近在用Wireshark做实验时候,需要清空本机ARP表和DNS缓存,所以在cmd窗口输入以下命令, 结果发生了错误:ARP项添加失败:请求的操作需要提升 一开始我还以为是操作的命令升级了,但是后面发现其实只是给的权…

为什么分类问题不能使用mse损失函数,更容易理解版本

分类问题通常不适合使用均方误差(Mean Squared Error,MSE)损失函数,原因如下: 1.输出差异: 输出差异的度量不同:MSE损失函数是基于预测值和真实值之间的差异的平方和进行计算的,适…

1小时学会SpringBoot3+Vue3前后端分离开发

首发于Enaium的个人博客 引言 大家可能刚学会Java和Vue之后都会想下一步是什么?那么就先把SpringBoot和Vue结合起来,做一个前后端分离的项目吧。 准备工作 首先你需要懂得Java和Vue的基础知识,环境这里就不多说了,直接开始。 …

DAC音频解码芯片DP7398立体声数模转换芯片

DP7398 Pin TO Pin CS4398和CS43122,同轴光纤DAC解码,支持HIFI播放器。 产品介绍 DP7398 是一个立体声 24 位/1 92kHz 数模转换芯片。 该 D/A 系统包括数字去加重、半分贝步长音量控制、 ATAP I 通道混频、可选择的快速和慢速数字插补滤波器和过采样多位…