网络编程
位置:首页>> 网络编程>> Go语言>> Golang数据类型比较详解

Golang数据类型比较详解

作者:xidianhuihui  发布时间:2023-07-17 10:11:21 

标签:Golang,数据,类型,比较

直接使用==比较的情况

分类说明是否能比较说明
基本类型整型( int/uint/int8/uint8/int16/uint16/int32/uint32/int64/uint64/byte/rune等)浮点数( float32/float64)复数类型( complex64/complex128)字符串( string)
引用类型切片(slice)、map
聚合类型(复合类型)数组相同长度的数组可以比较,不同长度的数组不能进行比较

结构体只包含可比较的类型情况下可比较
接口类型如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)
}

字符串比较

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

对比规则

  • 相同类型的值是深度相等的,不同类型的值永远不会深度相等。

  • 当数组值(array)的对应元素深度相等时,数组值是深度相等的。

  • 当结构体(struct)值如果其对应的字段(包括导出和未导出的字段)都是深度相等的,则该值是深度相等的。

  • 当函数(func)值如果都是零,则是深度相等;否则就不是深度相等。

  • 当接口(interface)值如果持有深度相等的具体值,则深度相等。

  • 当切片(slice)序号相同,如果值,指针都相等,那么就是深度相等的

  • 当哈希表(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看一下

Golang数据类型比较详解

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

Golang数据类型比较详解

针对这种情况,可以封装一个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)

来源:https://blog.csdn.net/xidianhuihui/article/details/130115443

0
投稿

猜你喜欢

  • MSDN:包含正在 SQL Server 实例上运行的进程的相关信息。这些进程可以是客户端进程或系统进程。 视图中主要的字段: 1. Spi
  • TNS简要介绍与应用 Oracle中TNS的完整定义:transparence Network Substrate透明网络底层,监听服务是它
  • 增大 SGA 已经缓冲看来对于性能的提升并不显著,加载时间只提升了 1.73%。下面我们增加 SGA 重做日志的大小: DB3: Log B
  • 第一种,也是我最常用的,第一帧里加上这个比较灵活,想要自定义加入菜单,只要定义drMenu这个对象就可以了var drMenu&n
  • 一、数据可视化1.pyecharts介绍官方网址:https://pyecharts.org/#/zh-cn/intro📣 概况:Echar
  • 事实上,互联网用户浏览网页的习惯和顾客浏览商店中物品的习惯没有多大差别。用户打开一个新的页面,扫视一些文字,并点击第一个引起他兴趣的链接。在
  • SQL Server 的扩展存储过程,其实就是一个普通的 Windows DLL,只不过按照某种规则实现了某些函数而已。近日在写一个扩展存储
  • /* 小弟刚刚接触ORACLE存储过程,有一个问题向各位同行求教,小弟写了一个存储过程,其目的是接收一个参数作为表名,然后查询该表中的全部记
  • 404错误是指在服务器找不到指定的页面。404错误页面是可以自定义的。Smashing Magazine为我们挑选了40个有创意的404错误
  • Adodb.Stream是ADO的Stream对象,提供存取二进制数据或者文本流,从而实现对流的读、写和管理等操作. 组件:&qu
  • 众所周知,IE 6只支持单通道的PNG图片(即只有透明/不透明2种状态,gif图片的透明单通道透明),因此如果需要使用alpha透明的png
  • 【译者的话】 网页上的小广告(banner)已经成为一种宣传推广的重要形式,但这些小广告除了版面细小外,图象的表现还受到象素较低等其它因素影
  • <%@LANGUAGE="xxx" CODEPAGE="936"%>一般又分为<%
  • 本人非计算机,亦非心理学,或者交互设计,更非设计专业出身,因此什么都是半桶水。即使如此,依然靠着兴趣寻找乐趣。对于设计,爱之,但没有受过系统
  • 天极网软件频道的图片切换特效,完全是由XHTML+CSS+JS实现的图片切换特效,弄了好半天啊!!如果您使用或者转载请别忘了加我的一个连接啊
  • function chinese2unicode(Str)       &nbs
  • JavaScript/Dom中有很多很零碎的东西,让人总是感觉理解的有些“朦胧”,因此,有时候还是应该总结一下,对于Event对象,前两天看
  • 惊现!表面下的隐藏信息——浅谈信息可视化1910年,病卧床上的魏格那(德国气象学家,以“大陆漂移学说”闻名),无意地注视着墙上的世界地图……
  • 又有人说设session.timeout=99999。这种同样不行,session有最大时间限制。我经过测试发现最大值为24小时,也就是说你
  • Window.ShowModalDialog使用手册 基本介绍: showModalDialog() (IE 4+ 支持) sho
手机版 网络编程 asp之家 www.aspxhome.com