Golang数据类型比较

news2025/1/12 18:18:24

直接使用==比较的情况

分类说明是否能比较说明
基本类型整型( int/uint/int8/uint8/int16/uint16/int32/uint32/int64/uint64/byte/rune等)浮点数( float32/float64)复数类型( complex64/complex128)字符串( string)
引用类型切片(slice)、map
channel、指针
聚合类型(复合类型)数组相同长度的数组可以比较,不同长度的数组不能进行比较
结构体只包含可比较的类型情况下可比较
接口类型如error

基本数据类

  • 类型一致且是基本类型,值相等的时候,才能==
  • 非基本类型会panic panic: runtime error: comparing uncomparable type []int

浮点比较

不过基本类型中也要注意浮点型的比较就不像我们现实中的一样,比如0.1+0.2在计算中运行结果就不是0.3了,而是0.30000000000000004了

package main import "fmt" func main() {     
    var a float64=0.1     
    var b float64=0.2     
    // 0.30000000000000004     
    fmt.Println(a+b) 
}

为什么会这样,可以看下draveness(https://github.com/draveness) 大佬的这篇文章https://draveness.me/whys-the…

字符串比较

一般的比较运算符(==、!=、<、<=、>=、>)是通过在内存中按字节比较来实现字符串比较的,因此比较的结果是字符串自然编码的顺序。字符串所占的字节长度可以通过函数 len() 来获取,例如 len(str)

比较两个字符是否相等

package golangbase

import (
	"fmt"
	"testing"
)

func TestString(t *testing.T) {
	str1 := "哈哈"
	str2 := "哈哈"
	fmt.Println(str1 == str2)
}

输出结果为true

引用类型

slice、map

  • 切片之间不允许比较。切片只能与nil值比较
  • map之间不允许比较。map只能与nil值比较
  • 两个nil也不能比较,会panic

slice、map比较

使用reflect.DeepEqual()

对比规则
  1. 相同类型的值是深度相等的,不同类型的值永远不会深度相等。
  2. 当数组值(array)的对应元素深度相等时,数组值是深度相等的。
  3. 当结构体(struct)值如果其对应的字段(包括导出和未导出的字段)都是深度相等的,则该值是深度相等的。
  4. 当函数(func)值如果都是零,则是深度相等;否则就不是深度相等。
  5. 当接口(interface)值如果持有深度相等的具体值,则深度相等。
  6. 当切片(slice)序号相同,如果值,指针都相等,那么就是深度相等的
  7. 当哈希表(map)相同的key,如果值,指针都相等,那么就是深度相等的。
使用示例
package golangbase

import (
	"reflect"
	"testing"
)

type StructA struct {
	Name  string
	Hobby []string
}

type StructB struct {
	Name string
}

func TestDeepEqual(t *testing.T) {
	s1 := StructA{Name: "test", Hobby: []string{"唱", "跳"}}
	s2 := StructA{Name: "test", Hobby: []string{"唱", "跳"}}
	println(reflect.DeepEqual(s1, s2))// true
	mp1 := map[int]int{1: 10, 2: 20}
	mp2 := map[int]int{1: 10, 2: 20}
	println(reflect.DeepEqual(mp1, mp2))// true
}

channel、指针

指针可比较,只要指针指向的地址一样,则相等

由于通过make创建channel后,返回的是一个指针,所以可以比较

c1 := make(chan int, 2) 
 
c2 := make(chan int, 2) 
 
c3 := c1 
 
fmt.Println(c3 == c1) // true 
 
fmt.Println(c2 == c1) // false 

聚合类型

数组

数组在go中是必须先确定长度的,也就是长度不能再去扩容。并且它是个值拷贝,做参数传到一个函数中被修改,那么外部的值还是一样的不变的。Slice则相反。那么数组是否可以比较呢,看下面的例子:

package main
import "fmt"
func main() {
    a := [2]int{1, 2}
    b := [2]int{1, 2}
    c := [2]int{1, 3}
    d := [3]int{1, 2, 4}
    fmt.Println(a == b) // true
    fmt.Println(a == c) // false
    fmt.Println(a == d) // invalid operation: a == d (mismatched types [2]int and [3]int)
}

可以看出,相同长度的数组是可以比较的,而不同长度的数组是不能进行比较的。原因是什么呢?这是因为数组类型中,数组的长度也是类型的一部分,不同长度的数组那么他们的类型也就被认为不同的,所以无法比较

结构体

只包含可比较的类型情况下可比较

package main
import "fmt"
type A struct {
    id int
    name string
}
func main() {
    a := A{id:5,name:"123"}
    b := A{id:5,name:"123"}
    c := A{id:5,name:"1234"}
    fmt.Println(a == b) // true
    fmt.Println(a == c) // false
}

反例,因为slice不可比较,如果结构体包含了slice,则不可比较

package main
import "fmt"
type A struct {
    id int
    name string
    son []int
}
func main() {
    a := A{id:5,name:"123",son:[]int{1,2,3}}
    b := A{id:5,name:"123",son:[]int{1,2,3}}
    fmt.Println(a == b) // invalid operation: a == b (struct containing []int cannot be compared)
}

接口

Go 语言根据接口类型是否包含一组方法将接口类型分成了两类:

  • 使用 runtime.iface结构体表示包含方法的接口
  • 使用 runtime.eface结构体表示不包含任何方法的 interface{} 类型
type eface struct { // 16 字节
    _type *_type
    data  unsafe.Pointer
}

type iface struct { // 16 字节
    tab  *itab
    data unsafe.Pointer
}

一个接口值是由两个部分组成的,即该接口对应的类型和接口对应具体的值

接口值的比较涉及这两部分的比较,只有当类型和值都相等(动态值使用==比较),两个接口值才是相等的。看个例子:

var a interface{} = 0
var b interface{} = 2
var c interface{} = 0
var d interface{} = 0.0
fmt.Println(a == b) // false
fmt.Println(a == c) // true
fmt.Println(a == d) // false

a和c类型相同(都是int),值也相同(都是0,基本类型比较),故两者相等。 a和b类型相同,值不等,故两者不等。 a和d类型不同,a为int,d为float64,故两者不等

最后做个练习

func TestJson(t *testing.T) {
	var x, y Data
	x = Data{
		UUID:    "856f5555806443e98b7ed04c5a9d6a9a",
		Content: 1,
	}
	bytes, _ := json.Marshal(x)
	_ = json.Unmarshal(bytes, &y)
	println(x)
	println(y)
	println(reflect.DeepEqual(x, y))
}

为什么结果为false?

debug看一下

img

原因是json.Unmarshal默认会将所有的数字类型转为float64

img

针对这种情况,可以封装一个DeepEqual方法

func DeepEqual(v1, v2 interface{}) bool {
	if reflect.DeepEqual(v1, v2) {
		return true
	}
	bytesA, _ := json.Marshal(v1)
	bytesB, _ := json.Marshal(v2)
	return bytes.Equal(bytesA, bytesB)
}

![在这里插入图片描述](https://img-blog.csdnimg.cn/55d294d1ab7740aba7b547d1a6165b5a.png)




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

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

相关文章

《Vue3实战》 第一章 nods/npm安装、配置

1、nods.js安装&#xff08;Windows&#xff09; 1.1、下载并安装node https://nodejs.org/en/ , 安装到d盘nodejs目录 1.2、配置环境变量 path配置 1.3、配置全局包存放目录和缓存目录 在根目录下创建node_global&#xff08;全局包存放目录&#xff09;和node_cache&…

关于药物|新药|药品市场调研报告(实操资料分享)

药品市场调研报告是指对药品行业进行详细的市场情况研究和分析。往往伴随着药品市场调研目的地不同&#xff0c;如战略探索、新药开发、投资决策等&#xff0c;报告编辑的内容要点要求也不一样。但总的核心要点内容笔者已提炼&#xff0c;如下&#xff1a; 一、药品市场调研报告…

DeePMD-kit 配置环境备忘

版本 Conda Conda是一个开源的包管理系统和环境管理系统&#xff0c;用于安装多个版本的软件包及其依赖项&#xff0c;并在它们之间轻松切换。它可以在Linux、OS X和Windows上运行&#xff0c;是为Python程序创建的&#xff0c;但可以打包和分发任何软件。 conda enactivatec…

为何ChatGPT如此擅长编造故事?

“幻觉”——人工智能中的一个偏见性术语 AI聊天机器人(如OpenAI的ChatGPT)依赖于一种称为“大型语言模型”(LLM)的人工智能来生成它们的响应。LLM是一种计算机程序&#xff0c;经过数百万文本源的训练&#xff0c;可以阅读并生成“自然语言”文本语言&#xff0c;就像人类自然…

TCP报头结构和TCP协议特性

TCP报头结构 原端口号/目的端口号&#xff1a;表示数据是从哪个进程来&#xff0c;到哪个进程去&#xff1b; 32位序号/32位确认号&#xff1a;这个序号是取的发送方发送所用数据下一个字节的序号&#xff0c;发送方的序列号和接收方的确认号一样&#xff0c;才算接收成功&…

敏捷开发模式下如何用 PingCode 这类工具进行版本发布管理

在软件团队工作中&#xff0c;版本发布要达到好的发布效果&#xff0c;需要在版本发布前做好版本发布的规划&#xff0c;并对发布流程和进度进行管理 准备工作&#xff1a; 您已经创建了一个 PingCode 帐户【快速注册入口】 您创建了一个 PingCode Scrum或 Kanban 项目 您的…

【周末闲谈】文心一言,模仿还是超越?

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️周末闲谈】 周末闲谈 ✨第一周 二进制VS三进制 文章目录周末闲谈前言一、背景环境二、文心一言&#xff1f;(_)?三、文心一言的优势&#xff1f;&#x1f617;&#x1f617;&#x1f617;四、文心一…

使用 arm 架构实例搭建 Harbor

使用 arm 架构实例搭建 Harbor事情准备&#xff08;使用甲骨文云上实例时的准备事项&#xff09;第1步&#xff0c;准备自签名证书第2步&#xff0c;安装Docker-ce第3步&#xff0c;构建arm镜像第4步&#xff0c;安装Harbor第5步&#xff0c;访问Harbor第6步&#xff0c;上传镜…

TensorFlow 深度学习第二版:1~5

原文&#xff1a;Deep Learning with TensorFlow Second Edition 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【ApacheCN 深度学习 译文集】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 不要担心自己的形象&#xff0c;只…

2023年【第十四届蓝桥杯】省赛java b组填空题

第一题 令 S 1! 2! 3! ... 202320232023!&#xff0c;求 S 的末尾 9 位数字。 提示&#xff1a;答案首位不为 0。 考试时的想法以及题解&#xff1a; 如果我们直接按照题目描述直接来求每个阶乘和的话恐怕没有什么数据类型能够胜任&#xff0c;在考试时我一开始使用了…

Linux中的read/write和recv/send的区别,并使用recv/send实现简单的聊天功能

Linux中的read/write和recv/send的区别read/writeread/writeread/write的用法recv/sendrecv/sendrecv/send的用法LinuxLinuxLinux中的read/writeread/writeread/write和recv/sendrecv/sendrecv/send的区别下面是一个使用read/write进行文件读写操作的例子&#xff1a;下面是一个…

【云原生】Kubernetes(k8s)部署 MySQL+Dubbo+Nacos服务

一、说明二、部署 MySQL三、部署 Nacos四、部署 Dubbo 服务4.1. 创建镜像仓库的密钥4.2. 部署 provider 服务4.3. 部署 consumer 服务五、测试一、说明 本文介绍基于 Kubernetes(k8s) 环境集成阿里云 私有镜像仓库 来部署一套 Dubbo Nacos 的微服务系统&#xff0c;并使用 Ku…

VUE前端项目环境搭建

背景&#xff1a; 想要使用vue搭建一个前端项目&#xff0c;写个小网站练练手&#xff0c;因为没有前端经验&#xff0c;所以从网上找了一个vue得开源模板使用&#xff0c;经过一番挑选选中了字节公司花裤衩大佬开源得项目&#xff0c;地址如下&#xff1a; 开源项目地址&…

第三代api自动化测试框架使用教程(pytest+allure+sql+yaml)

使用教程一、配置1、环境配置2、框架配置3、启动入口二、用例编写1、用例模板2、参数依赖写法2、函数&#xff08;方法插件&#xff09;写法3、接口上传文件和表单参数4、接口上传json参数5、接口无数据填写6、code断言7、body断言7、json断言8、sql断言9、完整断言写法&#x…

三种不同实现ublk的零拷贝I/O的方法

用户态块设备ublk&#xff0c;就是提供/dev/ublkbX这样的标准块设备给业务&#xff0c;业务读写这个块的实际IO处理由编写的用户态的代码决定。这就好比使用FUSE&#xff0c;所有对挂载于FUSE的目录的读写都是编写的IO handler来处理一样。使用用户态块设备&#xff0c;可以方便…

产品经理必读|用户研究方法总结①

众所周知&#xff0c;理解用户需求&#xff0c;识别用户痛点&#xff0c;是产品或功能成型之前绕不开的过程。而要获取到用户真实的需求和痛点&#xff0c;唯一的方法就是做用户调研。而用研的方法都有哪些呢&#xff1f;今天我就来给大家分享一下行业中常见的用研方法。 用研的…

ESP32设备驱动-VL53L0X飞行时间(激光测距)传感器驱动

VL53L0X飞行时间(激光测距)传感器驱动 文章目录 VL53L0X飞行时间(激光测距)传感器驱动1、VL53L0X介绍2、硬件准备3、软件准备4、驱动实现1、VL53L0X介绍 VL53L0X 是新一代飞行时间 (ToF) 激光测距模块,采用当今市场上最小的封装,与传统技术不同,无论目标反射率如何,都能提…

项目中开发固定表头和首列的表格【付代码】

前言 前段时间做移动端的项目&#xff0c;项目中需要一个固定表头和首列的表格&#xff0c;但由于是移动端的&#xff0c;组件库里没有类似的&#xff0c;于是&#xff0c;就去网上找看有没有类似的&#xff0c;结果越找越气&#xff0c;10个文章9个抄&#xff0c;抄也行&#…

安全狗入选网络安全行业全景图(第十版)多个细分领域

4月7日&#xff0c;安全牛正式发布第十版网络安全行业全景图。 作为国内云原生安全领导厂商&#xff0c;安全狗也凭借综合的安全能力脱颖而出入选全景图多个领域。 据悉&#xff0c;全景图报告调研基于企业自主申报&#xff0c;并对申报企业收录有严格要求&#xff0c;安全牛…

Zookeeper集群+Kafka集群

目录 一、Zookeeper Zookeeper 概述 定义 工作机制 Zookeeper特点 Zookeeper数据结构 ZooKeeper应用场景 统一命名服务 统一配置管理 统一集群管理 服务器动态上下线 软负载均衡 第一次启动选举机制 非第一次启动选举机制 二、部署Zookeeper集群 1、实验准备 2…