Go 快速入门指南 - 类型比较
2022/12/29 4:24:05
本文主要是介绍Go 快速入门指南 - 类型比较,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
概述
比较运算符
用来比较两个操作数并返回一个 bool
值,常见的比较运算符:
== 等于 != 不等于 < 小于 <= 小于等于 > 大于 >= 大于等于
在任何比较中,第一个操作数必须可以赋值给第二个操作数的类型,反过来也一样。
不可比较类型
Go 中有 3 种数据类型不能比较,分别是 slice
, map
, func
,如果要比较这 3 种类型, 使用 reflect.DeepEqual
函数。
为什么 slice 不能比较
(个人猜测,待验证)
-
• 切片是引用类型,比较地址没有意义
-
• 多个切片引用同一数组时,修改时会相互影响,无法保证
key
的一致性 -
• 切片除了
len
属性外,还有cap
属性,比较的维度没办法精确衡量
基于上述原因,官方没有支持 slice
类型的比较。
为什么 map 不能比较
(个人猜测,待验证)
- •
map
遍历是随机的,无法保证key
的一致性
为什么 func 不能比较
(个人猜测,待验证)
-
• 函数的可变参数机制,无法保证
key
的一致性 -
• 函数参数可以为
slice
,map
, 这两种类型不可比较
可比较类型的具体规则
-
•
布尔值
可比较 -
•
整型
可比较 -
•
浮点型
可比较。如果两个浮点型值一样 (由IEEE-754
标准定义),则两者相等 -
•
复数型
可比较。如果两个复数型值的real()
方法 和imag()
方法都相等,则两者相等 -
•
字符串
可比较 -
•
指针
可比较。如果两个指针指向相同的地址
或者两者都为nil
,则两者相等,但是指向不同的零大小变量的指针可能不相等 -
•
通道
可比较。如果两个通道是由同一个make
创建的 (引用的是同一个 channel 指针),或者两者都为nil
, 则两者相等 -
•
接口
可比较。interface
的内部实现包含了 2 个字段,类型T
和 值V
。如果两个接口
具有相同的动态类型和动态值,或者两者都为nil
, 则两者相等 -
•
结构体
可比较 (如果两个结构体的所有字段都是可比较的)。如果两个结构体对应的非空白字段相等,则两者相等 -
•
数组
可比较 (如果两个数组的所有元素都是可比较的)。如果两个数组的所有对应元素相等,则两者相等
例子
指针的比较
指向相同的地址的指针
package main import "fmt" func main() { n := 1024 p := &n p2 := &n fmt.Printf("p == p2: %t\n", p == p2) } // $ go run main.go // 输出如下 /** p == p2: true */
指向 nil 的指针
package main import "fmt" func main() { var p *string var p2 *string fmt.Printf("p == p2: %t\n", p == p2) } // $ go run main.go // 输出如下 /** p == p2: true */
通道的比较
同一个 make() 创建的通道
package main import "fmt" func main() { ch := make(chan bool) ch2 := make(chan bool) p := &ch p2 := &ch2 fmt.Printf("p == p2: %t\n", p == p2) p3 := &ch fmt.Printf("p == p3: %t\n", p == p3) } // $ go run main.go // 输出如下 /** p == p2: false p == p3: true */
通道为 nil
package main import "fmt" func main() { var p *chan bool var p2 *chan bool fmt.Printf("p == p2: %t\n", p == p2) } // $ go run main.go // 输出如下 /** p == p2: true */
结构体的比较
比较的前提: 两个结构体的所有字段都是可比较的,相等是指: 字段类型、字段个数、字段顺序、字段值完全一致。
结构体对应的非空白字段相等
package main import "fmt" type person struct { name string age int } func main() { tom := person{ name: "Tom", age: 6, } jerry := person{ name: "Jerry", age: 8, } fmt.Printf("tom == jerry: %t\n", tom == jerry) nobody := person{} nobody2 := person{} fmt.Printf("nobody == nobody2: %t\n", nobody == nobody2) } // $ go run main.go // 输出如下 /** tom == jerry: false nobody == nobody2: true */
结构体为 nil
package main import "fmt" type person struct { name string age int } func main() { var nobody person var nobody2 person fmt.Printf("nobody == nobody2: %t\n", nobody == nobody2) } // $ go run main.go // 输出如下 /** nobody == nobody2: true */
接口的比较
具有相同的动态类型和动态值
package main import "fmt" type person struct { name string } func main() { var tom1, tom2 interface{} tom1 = &person{"Tom"} tom2 = &person{"Tom"} var tom3, tom4 interface{} tom3 = person{"Tom"} tom4 = person{"Tom"} fmt.Printf("tom1 == tom2: %t\n", tom1 == tom2) // false fmt.Printf("tom3 == tom4: %t\n", tom3 == tom4) // true } // $ go run main.go // 输出如下 /** tom1 == tom2: false tom3 == tom4: true */
上面的示例代码中,tom1 和 tom2 对应的类型是 *person,值是 person 结构体的地址,但是两个地址不同,因此两者不相等, tom3 和 tom4 对应的类型是 person,值是 person 结构体且各字段相等,因此两者相等。
接口为 nil
package main import "fmt" func main() { var tom1, tom2 interface{} fmt.Printf("tom1 == tom2: %t\n", tom1 == tom2) // true } // $ go run main.go // 输出如下 /** tom1 == tom2: true */
小结
本小节介绍了 Go 的比较运算符以及各种数据类型的比较规则。Go 中大多数数据类型都是可以比较的, 除了 slice
, map
, func
这 3 种,对于不能比较的原因,笔者给出了一些猜测,感兴趣的读者可以自行验证。限于时间和篇幅,没有给出所有数据类型的代码示例,读者可以编写代码验证具体的类型比较规则。
这篇关于Go 快速入门指南 - 类型比较的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-15SendGrid 的 Go 客户端库怎么实现同时向多个邮箱发送邮件?-icode9专业技术文章分享
- 2024-11-15SendGrid 的 Go 客户端库怎么设置header 和 标签tag 呢?-icode9专业技术文章分享
- 2024-11-12Cargo deny安装指路
- 2024-11-02MongoDB项目实战:从入门到初级应用
- 2024-11-01随时随地一键转录,Google Cloud 新模型 Chirp 2 让语音识别更上一层楼
- 2024-10-25Google Cloud动手实验详解:如何在Cloud Run上开发无服务器应用
- 2024-10-24AI ?先驱齐聚 BAAI 2024,发布大规模语言、多模态、具身、生物计算以及 FlagOpen 2.0 等 AI 模型创新成果。
- 2024-10-20goland工具下,如修改一个项目的标准库SDK的版本-icode9专业技术文章分享
- 2024-10-17Go学习:初学者的简单教程
- 2024-10-17Go学习:新手入门完全指南