深入理解Go语言中的可比较数据类型

文章目录

  • 前言
  • 1 可比较数据类型是什么?
  • 2 可比较数据类型有哪些?
  • 3 基本数据类型比较
    • 3.1 不同数据类型比较是无效的
    • 3.2 实现不同数据类型比较:转换同数据类型
  • 4 指针数据类型比较
  • 5 接口类型比较
    • 5.1 方式1:设置动态数据类型和动态值
    • 5.2 方式2:通过接口提供结构体行为
  • 6 如何解决数据类型不可比较的问题?
    • 6.1 比较切片Slice
    • 6.2 比较映射 (Map)
    • 6.3 比较函数变量
  • 7 知识总结

前言

本文详细解释了什么是可比较数据类型,列出了Go语言中哪些数据类型是可比较的,并通过具体示例讲解了基本数据类型、指针类型和接口类型的比较规则。文章还介绍了如何通过类型转换实现不同数据类型的比较,帮助读者深入理解和掌握这些知识。


1 可比较数据类型是什么?

在GO语言中,支持使用 == 和 != 运算符来比较的数据类型,我们称为“可比较数据类型”。


2 可比较数据类型有哪些?

在GO语言中,支持可比较的数据类型有:基本数据类型(布尔类型、整数类型、浮点数类型、复数类型、字符串类型)、指针类型复合数据类型(数组、结构体、切片、map、函数)
注意事项:复合数据类型中的切片map,它们是引用数据类型,不能直接进行比较的,只能与 nil 进行比较。函数类型不能比较,但可以与 nil 进行比较。


3 基本数据类型比较

基本数据类型的比较是根据两个相同数据类型的值是否相等,不同数据类型是不能直接进行比较的,需转换为相同的数据类型后再进行比较。下面是代码示例。


3.1 不同数据类型比较是无效的

基本数据类型若两个是不同的数据类型,是无法直接进行比较的,会导致编译错误

func main() {  var num int = 10  var floatNum float32 = 10  fmt.Println(num == floatNum)  
}// 编译错误:invalid operation: num == floatNum (mismatched types int and float32)
// 提示我们不同的数据类型进行比较是无效的。

3.2 实现不同数据类型比较:转换同数据类型

想要解决基本数据类型中的两个不同数据类型的比较,必须先转换为同一种数据类型后,再进行比较。

func main() {  var num int = 10  var floatNum float32 = 10  floatNum1 := float32(num)  fmt.Println(floatNum == floatNum1)  
}// 返回结果:true

4 指针数据类型比较

指针数据类型比较的依据:判断指针指向变量的内存地址是否相等。

func main() {  // 声明变量  var a int = 10  // 取a的地址  var b *int  b = &a  // 取b的值  var c *int  c = b  // 判断a和c的地址是否相等  println(&a == c)  
}
// 返回结果: true

5 接口类型比较

接口数据类型有两种使用方式,一种是设置动态数据类型和动态值,一种是通过接口提供结构体行为。第一种方式是可比较的,但不仅仅比较动态值是否相等,还会比较其动态类型是否相同。第二种方式中,当接口的动态类型所引用的结构体包含引用类型字段(如map或者slice)时,该接口变量不可进行比较,会导致编译错误


5.1 方式1:设置动态数据类型和动态值

接口数据类型设置动态数据类型和动态值是可比较的,比较其动态数据类型和动态值是否相等。

func main() {  var a interface{}  var b interface{}  a = 1  b = 1 fmt.Println(a == b)   // 输出: true,动态数据类型(int)和动态值相等a = 1  b = "hello"  fmt.Println(a == b)  // 输出: false,动态数据类型(int)和动态数据类型(string)不等
}

5.2 方式2:通过接口提供结构体行为

当接口的动态类型所引用的结构体包含引用类型字段(如map或者slice)时,该接口变量不可进行比较,会导致编译错误

// 定义一个接口
type Speaker interface {Speak() string
}// 定义一个包含不可比较字段的结构体
type Cat struct {Name  stringToys  []string // 切片是不可比较的
}// Cat 实现了 Speaker 接口
func (c Cat) Speak() string {return c.Name + " says: Meow!"
}func main() {var s1, s2 Speakerc1 := Cat{Name: "Kitty", Toys: []string{"Ball", "Mouse"}}c2 := Cat{Name: "Kitty", Toys: []string{"Ball", "Mouse"}}s1 = c1s2 = c2// fmt.Println(s1 == s2) // 编译错误:切片类型不可比较
}

6 如何解决数据类型不可比较的问题?

如果有不可比较数据类型(slicemap函数变量),使用reflect反射包(relect.DeepEqual())来进行深度判断。


6.1 比较切片Slice

reflect.DeepEqual 可以递归地比较切片的元素。如果两个切片的元素相同,顺序相同,reflect.DeepEqual 会返回 true

func main() {slice1 := []int{1, 2, 3}slice2 := []int{1, 2, 3}slice3 := []int{4, 5, 6}fmt.Println(reflect.DeepEqual(slice1, slice2)) // 输出:truefmt.Println(reflect.DeepEqual(slice1, slice3)) // 输出:false
}

6.2 比较映射 (Map)

reflect.DeepEqual 可以递归地比较映射的键值对。如果两个映射的键值对相同,reflect.DeepEqual 会返回 true

func main() {map1 := map[string]int{"a": 1, "b": 2}map2 := map[string]int{"a": 1, "b": 2}map3 := map[string]int{"a": 1, "b": 3}fmt.Println(reflect.DeepEqual(map1, map2)) // 输出:truefmt.Println(reflect.DeepEqual(map1, map3)) // 输出:false
}

6.3 比较函数变量

对于函数变量,reflect.DeepEqual 会比较两个函数变量是否指向同一个函数。如果它们指向不同的函数,即使函数体相同,比较结果也会是 false

func main() {f1 := func() {fmt.Println("Hello, Go!")}f2 := func() {fmt.Println("Hello, Go!")}f3 := f1fmt.Println(reflect.DeepEqual(f1, f2)) // 输出:false,不同的函数实例fmt.Println(reflect.DeepEqual(f1, f3)) // 输出:true,相同的函数实例
}

7 知识总结

[!example] 知识总结

  • 基本数据类型比较:相同数据类型可比较,不同数据类型不可比较,必须先转换同类型后比较。
  • 指针数据类型比较:判断的是指针指向的变量内存地址是否相等
  • 复合数据类型比较:数组判断所有元素是否相等;结构体中的所有字段(非不可比较字段)是否相等;切片、map和函数都是不可比较的,只能判断是否为nil。
  • 接口数据类型比较:当设置动态数据类型和动态值时,是可比较的;当接口的动态类型所引用的结构体包含引用类型字段(如map或者slice)时,该接口变量不可进行比较
  • 解决数据类型不可比较问题:切片、map、函数变量使用reflect包中的 reflect.DeepEqual 用于比较,切片和映射是递归比较它们的内容内容相同返回true;函数变量会判断两个函数是否指向同一个函数,并返回true.

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

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

相关文章

依据SAM大模型识别的英国农田(农业田野)边界(FIBOA)矢量数据集

简介 fiboa 是一项旨在提高农田边界数据互操作性和相关农业数据的合作计划。最近推出的 fiboa 不仅仅是一个规范,它还是一个全面的系统,包括符合规范的数据、不断完善规范的讨论以及积极促进其发展的活跃社区。本项目的重点是促进创建更多有关田地边界和…

用c语言实现简易三子棋

本篇适用于C语言初学者。 目录 完整代码&#xff1a; 分步介绍&#xff1a; 声明&#xff1a; 代码主体部分&#xff1a; 模块功能实现&#xff1a; 完整代码&#xff1a; #include<stdio.h> #include <stdlib.h> #include <time.h>#define ROW 3 #d…

黑马程序员——Spring框架——day03

目录&#xff1a; AOP AOP简介 问题导入AOP简介和作用【理解】AOP的应用场景为什么要学AOPAOP入门案例【重点】 问题导入AOP入门案例思路分析AOP入门案例实现AOP中的核心概念AOP工作流程【理解】 问题导入AOP工作流程AOP核心概念在测试类中验证代理对象AOP切入点表达式 问题导…

【python】爬虫记录每小时金价

数据来源&#xff1a; https://www.cngold.org/img_date/ 因为这个网站是数据随时变动的&#xff0c;用requests、BeautifulSoup的方式解析html的话&#xff0c;数据的位置显示的是“--”&#xff0c;并不能取到数据。 所以采用webdriver访问网站&#xff0c;然后从界面上获取…

webserver服务器从零搭建到上线(十)|⭐️EventLoop类(二)——成员方法详解

首先&#xff0c;在阅读本章之前&#xff0c;我们需要搞清楚为什么EventLoop类这么复杂 其次&#xff0c;我们还需要再强调一次关于mainLoop唤醒subLoop的流程&#xff08;可以看完该类代码后再回顾该流程&#xff09;&#xff1a; 为什么需要唤醒 subLoop? subLoop&#xff0…

C语言 指针——函数指针的典型应用:计算定积分

目录 梯形法计算函数的定积分 函数指针的典型应用 梯形法计算函数的定积分 函数指针的典型应用 用函数指针编写计算任意函数定积分的 通用 函数

15届蓝桥杯决赛,java b组,蒟蒻赛时所写的题思路

这次题的数量是10题&#xff0c;初赛是8题&#xff0c;还多了两题&#xff0c;个人感觉java b组的题意还是比较清晰的&#xff08;不存在读不懂题的情况&#xff09;&#xff0c;但是时间感觉还是不够用&#xff0c;第4题一开始不会写&#xff0c;后面记起来写到结束也没调出来…

Vivado 比特流编译时间获取以及FPGA电压温度获取(实用)

Vivado 比特流编译时间获取以及FPGA电压温度获取 语言 &#xff1a;Verilg HDL 、VHDL EDA工具&#xff1a;ISE、Vivado Vivado 比特流编译时间获取以及FPGA电压温度获取一、引言二、 获取FPGA 当前程序的编译时间verilog中直接调用下面源语2. FPGA电压温度获取&#xff08;1&a…

深度学习中测量GPU性能的方式

在深度学习中&#xff0c;测量GPU性能是至关重要的步骤&#xff0c;尤其是在训练和推理过程中。以下是一些常见的测量GPU性能的方式和详细解释&#xff1a; 1. 运行时间&#xff08;Runtime&#xff09;测量 描述&#xff1a;运行时间测量是评估GPU性能的最直接方式&#xff…

es的总结

es的collapse es的collapse只能针对一个字段聚合&#xff08;针对大数据量去重&#xff09;&#xff0c;如果以age为聚合字段&#xff0c;则会展示第一条数据&#xff0c;如果需要展示多个字段&#xff0c;需要创建新的字段&#xff0c;如下 POST testleh/_update_by_query {…

信息与未来2015真题笔记

[信息与未来 2015] 加数 题目描述 给出一个正整数 n n n&#xff0c;在 n n n 的右边加入 ⌊ n 2 ⌋ \left\lfloor\dfrac n2\right\rfloor ⌊2n​⌋&#xff0c;然后在新数的右边 再加入 ⌊ ⌊ n 2 ⌋ 2 ⌋ \left\lfloor\dfrac{\left\lfloor\dfrac n2\right\rfloor}2\rig…

MyBatis:PostGreSQL的jsonb类型处理器

接前一篇《MyBatis Plus:自定义typeHandler类型处理器》,这里介绍PostGreSQL数据库的jsonb数据类型,以及如何实现jsonb类型处理器。 PostGreSQL:jsonb数据类型 json和jsonb之间的区别 PostgreSQL 提供存储JSON数据的两种类型:json 和 jsonb,两者之间的区别在于: js…

JVM学习-详解类加载器(一)

类加载器 类加载器是JVM执行类加载机制的前提 ClassLoader的作用 ClassLoader是Java的核心组件&#xff0c;所有的Class都是由ClassLoader进行加载的&#xff0c;ClassLoader负责通过各种方式将Class信息的二进制数据流读入JVM内部&#xff0c;转换为一个与目标类型对应的ja…

Java学习【String类详解】

Java学习【String类详解】 String的介绍及定义方式String类型的比较String类型的查找charAt()访问字符indexOf()查找下标 转化和替换数值和字符串转化大小写的转换字符串转数组格式化替换 字符串的拆分和截取split()拆分substring()截取trim()去除两边空格 StringBuilder和Stri…

苏州金龙客车为新疆哪吒车队提供车辆交车

2024年旅游旺季提前到来、时间延长&#xff0c;新疆旅游市场有望延续去年火爆态势。 近期&#xff0c;新疆哪吒运输服务有限公司&#xff08;以下简称“哪吒车队”&#xff09;订购的最新一批10辆苏州金龙海格高端旅游大巴在苏州金龙厂区正式交付。哪吒车队负责人伍亚丽笑容满…

SpringCloud学习笔记万字整理(无广版在博客)

在此感谢黑马程序员的SpringCloud课程 所有笔记、生活分享首发于个人博客 想要获得最佳的阅读体验&#xff08;无广告且清爽&#xff09;&#xff0c;请访问本篇笔记 认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐…

python的元组

元组与列表的区别 元组和列表非常相似。不同之处在于&#xff0c;外观上&#xff1a;列表是被 方括号 包裹起来的&#xff0c;而元组是被 圆括号 包裹起来的。本质上&#xff1a;列表里的元素可修改&#xff0c;元组里的元素是 不可以“增删改” 。 还有一个微妙的地方要注意…

数据分析——Excel篇

1*学习碎片知识点记录&#xff1a; CtrlshiftL 筛选 UV&#xff08;Unique visitor&#xff09;&#xff1a;是指通过互联网访问、浏览这个网页的自然人。访问网站的一台电脑客户端为一个访客。00&#xff1a;00-24&#xff1a;00相同的客户端只被计算一次&#xff0c;一天内…

MK SD NAND(贴片式SD卡)在电力AI模块中的应用案例

近期一位客户&#xff0c;在网上了解到我们SD NAND后联系到我们&#xff0c;经过一系列了解对比后&#xff0c;下单了我们的SD NAND产品。 这位客户是做电力AI模块的&#xff0c;他们的产品主要应用在电力行业。 电力AI模块是集成了人工智能技术的系统&#xff0c;专门设计用于…

fpga控制dsp6657上电启动配置

1 Verilog代码 dspboot_config.v timescale 1ns / 1ps //dsp上电启动配置 module dspboot_config (///时钟和复位input SYS_CLK_50MHz,input SYS_RST_n,//DSP启动配置output DSP_POR,output DSP_RESETFULL,output DSP_RESET,inout [12:…