关于 interface{} 会有啥注意事项?上

news2024/9/21 2:36:52

学习 golang ,对于 interface{} 接口类型,我们一定绕不过,咱们一起来看看 使用 interface{} 的时候,都有哪些注意事项吧

interface {} 可以用于模拟多态

xdm 咱们写一个简单的例子,就举动物的例子

写一个 Animal 的接口,类似于 java 里面的抽象类 ,Animal 的接口 中有 2 个方案待实现

写一个 Cat 来继承 Animal实现 Eat 方法和 Drink 方法

  • 动物都有吃和喝的行为,小猫吃的行为是吃鱼,小猫的喝的行为是喝可乐
  • 最后在主函数中,使用父类的指针,来指向子类的实例化的一个子类地址
type Animal interface {
	Eat(string) string
	Drink(string) string
}

type Cat struct{}

func (c *Cat) Eat(food string) string {
	if food != "fish" {
		return "i dislike"
	} else {
		return "i like"
	}

}
func (c *Cat) Drink(drink string) string {
	if drink == "coke" {
		return "i love"
	}else{
		return "abandon"
	}
}
func main(){
	var a Animal = &Cat{}
	fmt.Println(a.Eat("fish"))
	fmt.Println(a.Drink("water"))
}

看到上述代码,会不会有这样的疑问,命名是 &Cat{} 是取地址的,为什么 var a Animal 不写成指针呢?

这里需要注意,Animal 本身是 接口类型,自身就是一个指针

运行上述代码查看效果

# go run main.go
i like
abandon

没有毛病,小猫眯爱吃鱼,不爱喝水

interface{} 需要注意空和非空的情况

什么叫做空的 interface{} , 什么又叫做非空的 interface{} 呢?

咱们还是用上面的例子, 添加一个 testInterface 函数,来实践一下

func testInterface() Animal {
	var c *Cat
	return c
}

func main() {
	test := testInterface()
	if test == nil {
		fmt.Println("test is nil")
	} else {
		fmt.Println("test is not nil")
	}
}

可以猜猜看,上面这个小案例会输出什么结果

  • 理论上来看,testInterface 函数中我们只是创建了一个 Cat 指针,并没有赋值,因此默认是一个零值,因此会是一个 nil,那么 return 的时候,应该也是 return nil 才对吧,因此按照代码的逻辑来说应该是输出 test is nil

执行上述代码后,查看结果

# go run main.go
test is not nil

看到上面的结果,是不是觉得很奇怪,和自己的预期不一致

没关系,之前的文章我们说到过,觉得一个技术点奇怪,不是我们所期望的效果,原因是我们对其原理不够了解,不够熟悉

现在先来回答一下上面的问题

空接口:意思是没有方法的接口,interface{} 源码中表示为 eface 结构体

非空接口:表示有包含方法的接口 , interface{} 源码中表示为 iface 结构体

暂时先来直接介绍源码中的结构体

iface 结构体 , 非空

type iface struct {
	tab  *itab
	data unsafe.Pointer
}

type itab struct {
	inter  *interfacetype
	_type  *_type
	link   *itab
	hash   uint32 // copy of _type.hash. Used for type switches.
	bad    bool   // type does not implement interface
	inhash bool   // has this itab been added to hash?
	unused [2]byte
	fun    [1]uintptr // variable sized
}
  • tab

    指的是具体的类型信息,是一个 itab 结构,结构中成员如上,这里面包含的都是借口的关键信息,例如 hash 值 ,函数指针,等等,后续详细剖析 interface{} 原理的时候再统一说

  • data

具体的数据信息

eface 结构体

type eface struct {
    _type *_type
    data  unsafe.Pointer
}
type _type struct {
    size       uintptr  // 表示的是 类型的大小
    ptrdata    uintptr  // 值的是前缀指针的内存大小
    hash       uint32   // 计算数据的 hash 值
    tflag      tflag
    align      uint8    //  进行内存对齐的
    fieldalign uint8 
    kind       uint8 
    alg        *typeAlg 
    gcdata    *byte
    str       nameOff
    ptrToThis typeOff
}
  • _type

类型信息,和上面的 非空接口类似 , 这个_type 类型决定下面的 data 字段如何去解释数据

  • data

具体的数据信息

看到这里,细心的 xdm 是不是就可以看出来,我们上面写的 Animal 接口,其实是一个非空接口,因为里面有包含方法,所以他的底层是一个 iface 结构体 ,非空接口

那么初始化的一个空指针 c ,实际上是 iface 结构体里面的 data 字段为空而已,数据为空而已,但是 iface 这个结构体自己不是空的,所以上述代码走的逻辑是 test is not nil

这里顺带说一下,golang 中,还有哪些数据结构是和 nil 比较是否为零值,这个点我们也可以看看源码

// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
var nil Type // Type must be a pointer, channel, func, interface, map, or slice type

源码中有说到,可以对 指针,通道,函数,接口,map,切片类型使用 nil

好了,本次就到这里,知识点要用起来才有价值

欢迎点赞,关注,收藏

朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

好了,本次就到这里

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

我是阿兵云原生,欢迎点赞关注收藏,下次见~

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

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

相关文章

【LeetCode】剑指 Offer(17)

目录 题目:剑指 Offer 34. 二叉树中和为某一值的路径 - 力扣(Leetcode) 题目的接口: 解题思路: 代码: 过啦!!! 写在最后: 题目:剑指 Offer …

Spring Cache简单介绍和使用

目录 一、简介 二、使用默认ConcurrentMapManager (一)创建数据库和表 (二)创建boot项目 (三)使用Api 1、EnableCaching 2、CachePut 3、cacheable 4、CacheEvict 三、使用redis作为cache 一、简…

云计算基础——云计算认知

云计算的总体框架在服务方面,主要以提供用户基于云的各种服务为主,共包含3个层次:1.软件即服务(Software as a Service,简称SaaS),这层的作用是将应用主要以基于Web 的方式提供给客户;2.平台即服务(Platform as a Serv…

STL讲解——模拟实现vector

STL讲解——模拟实现vector vector深度剖析 在STL源码中,发现vector定义的并不是 start、size、capacity,而是start、finish、end_of_storage. 这样就可以得到size()和capacity()。 sizefinish-start capacityend_of_storage-start 扩容可能是本地扩容也…

Entity Framework简单使用

我喜欢比较老派的database first , 所以先创建sql server的数据库,比如dbname叫做:Blogging这里我省略了。 在visual studio里面创建一个控制台程序, 然后添加ado.net项目 选择“gen from database” 然后新建你的数据库连接&…

基于粒子群优化算法的分布式电源选址定容【IEEE33节点】(Matlab代码实现)

👨‍🎓个人主页:研学社的博客💥💥💞💞欢迎来到本博客❤️❤️💥💥🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密…

测试人员须要知道的性能测试那些事

随着各企业的业务发展、用户量以及数据量的不断增加,系统承载的压力也会随之增加,服务系统的性能好坏又严重影响企业的利益。因此,性能测试重要性与需求越来越强烈。 常见的性能测试目的 性能测试是确定系统在特定工作负载下的稳定性和响应…

数智引航 共赢未来 | 科士达2023数据中心合作伙伴大会圆满召开!

3月5日,科士达2023年全国合作伙伴大会在广东深圳隆重召开,本次大会以“数智引航 共赢未来”为主题,来自全国各地的核心渠道伙伴齐聚一堂,深度交流,展望未来,共同探讨数据中心技术发展趋势,碰撞…

[Python图像处理] 使用高通滤波器实现同态滤波

使用高通滤波器实现同态滤波同态滤波基础实现同态滤波相关链接同态滤波基础 同态滤波是一种去除图像中乘性噪声的技术,常用于校正图像中的不均匀照明。根据图像形成的光照反射模型,图像 f(x,y)f(x,y)f(x,y) 可以由以下两个分量表征: 入射到…

linux中改变了jdk版本,为什么其他用户无法使用?

linux中改变了jdk版本,为什么其他用户无法使用? 1、jdk建在/usr/local目录下 2、环境变量写在/etc/profile下 3、如果发现root用户下,java -version可以出现版本信息,其他用户下查询不到jdk版本信息 问题:root用户下&…

关于递归处理,应该怎么处理,思路是什么?

其实问题很简单,就是想要循环遍历整个data对象,来实现所有name转成label,但是想到里面还有children属性,整个children里面可能还会嵌套很多很多的name,如此循环,很难搞,知道使用递归&#xff0c…

Linux系统安装Hbase,通过Zookeeper管理

目录 一、安装包解压,重命名 二、修改环境配置 2.1、修改 Hbase配置 2.2、修改 zookeeper配置 2.3、修改/etc/profile 环境,添加Hbase和Zookeeper环境路径 三、启动Hbase 四、退出服务 一、安装包解压,重命名 安装包:链接…

数据分析:基于随机森林(RFC)对酒店预订分析预测

数据分析:基于随机森林(RFC)对酒店预订分析预测 作者:AOAIYI 作者简介:Python领域新星作者、多项比赛获奖者:AOAIYI首页 😊😊😊如果觉得文章不错或能帮助到你学习,可以点赞&#x1f…

微信小程序上拉、下拉刷新组封装件

在开发小程序的时候通常会遇到上拉或者下拉刷新的功能需求&#xff0c;然而这个功能很多页面也都会用到&#xff0c;因此这里&#xff0c;把这个功能封装为组件&#xff0c;方便复用 我很直接&#xff0c;不多说&#xff0c;上代码 首先index.wxml <scroll-view scroll-y…

LNMP架构的源码编译环境下部署 Discuz!社区论坛与Wordpress博客

目录 一.编译安装Nginx 1.关闭防火墙 2.安装依赖包 3.创建运行用户 4.解压软件包并编译安装 5.软链接路径优化 6.添加Nginx系统服务 二.编译安装MySQL服务 1.安装依赖环境 2.创建运行用户 3.解压软件包并编译安装 4.数据库目录进行权限调整 5.修改配置文件 6.设…

linux面试基础篇

题目目录1.简述DNS分离解析的工作原理&#xff0c;关键配置2.apache有几种工作模式&#xff0c;分别简述两种工作模式及其优缺点&#xff1f;3.写出172.0.0.38/27 的网络id与广播地址4.写出下列服务使用的传输层协议&#xff08;TCP/UDP&#xff09;及默认端口5.在局域网想获得…

Uni-app页面路由的几种写法

uni.navigateTo( OBJECT) 保留当前页面&#xff0c;跳转到应用内的某个页面&#xff0c;使用 uni.navigateBack 可以返回到原来页面 ONJECT参数说明&#xff1a; 注意&#xff1a; 页面跳转路径有层级限制&#xff0c;不能无限跳转新页面跳转到 tabBar 页面只能使用 switchT…

NCRE计算机等级考试Python真题(十二)

第十二套试题1、以下关于程序设计语言的描述&#xff0c;错误的选项是&#xff1a;A.Python语言是一种脚本编程语言B.汇编语言是直接操作计算机硬件的编程语言C.程序设计语言经历了机器语言、汇编语言、脚本语言三个阶段D.编译和解释的区别是一次性翻译程序还是每次执行时都要翻…

LCD液晶段码屏显示驱动IC -VK2C23高抗干扰/抗噪,适用于瓦斯表/燃气表/煤气表

产品型号&#xff1a;VK2C23A/B产品品牌&#xff1a;永嘉微电/VINKA封装形式&#xff1a;LQFP64/48可定制&#xff1a;DICE(COB邦定片)&#xff1b;COG(邦定玻璃用)产品年份&#xff1a;新年份原厂 工程服务&#xff0c;技术支持&#xff01;VK2C23A/B概述&#xff1a;VK2C23A/…

微信小程序this指向问题

前言 最近在开发微信小程序时不时会遇到一个很奇怪的问题&#xff0c;有些情况下用 this.setData 可以改变视图显示&#xff0c;有些情况下使用 this.setData 无效&#xff0c;这又是为什么呢&#xff1f; 问题描述 在解释这个问题前&#xff0c;我们先来看两段代码&#xff1…