开发者

Golang数据类型比较详解

开发者 https://www.devze.com 2023-04-13 11:18 出处:网络 作者: xidianhuihui
目录 基本数据类浮点比较字符串比较引用类型slice、mapslice、map比较channel、指针聚合类型数组结构体接口最后做个练习直接使用==比较的情况
目录
  •  基本数据类
    • 浮点比较
    • 字符串比较
  • 引用类型
    • slice、map
      • slice、map比较
    • channel、指针
    • 聚合类型
      • 数组
        • 结构体
          • 接口
          • 最后做个练习

            直接使用==比较的情况

            分类说明是否能比较说明
            基本类型整型( 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   python  
                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 typjavascriptes [2]int and [3]int)android
            }
            

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

            结构体

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

            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 字节
                _tyhttp://www.devze.compe *_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开发者_C开发.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)
            
            
            
            
            

            以上就是Golang数据类型比较详解android的详细内容,更多关于Golang数据类型比较的资料请关注我们其它相关文章!

            0

            精彩评论

            暂无评论...
            验证码 换一张
            取 消

            关注公众号