美文网首页
go笔记 - 赋值和值比较规则

go笔记 - 赋值和值比较规则

作者: 陈德华 | 来源:发表于2020-10-09 16:07 被阅读0次

1、赋值规则

赋值可以看作是隐式类型转换

赋值语句中的目标值必须为一个可寻址的值、一个映射元素表达式或者一个空标识符。

在一个赋值中,源值被复制给了目标值。精确地说,源值的直接部分被复制给了目标值。


2、值比较规则

在任何比较中,第一个比较值必须能被赋值给第二个比较值的类型,或者反之。

所以,值比较规则和赋值规则非常相似。 换句话说,两个值是否可以比较取决于其中一个值是否可以隐式转换为另一个值的类型。 但是有一个例外:

如果两个值中有一个为接口值,而另一个为非接口值并且它的类型为一个不可比较类型,则这两个值不可比较,即使此非接口值可以被隐式转换为接口值的类型(即此不可比较类型实现了接口值的类型)。

注意,尽管切片/映射/函数类型为不可比较类型,但是它们的值可以和类型不确定的预声明nil标识符比较。

上述规则并未覆盖所有的情况。如果两个值均为类型不确定值,它们可以比较吗?这种情况的规则比较简单:

两个类型不确定的布尔值可以相互比较。

两个类型不确定的数字值可以相互比较。

两个类型不确定的字符串值可以相互比较。

两个类型不确定的数字值的比较结果服从直觉。

注意,两个类型不确定的nil值不能相互比较。

var s []int

var m map[int]int

var f func()()

var t struct {x []int}

var a [5]map[int]int

func main() {

// 这些比较编译不通过。

     _ = s == s

    _ = m == m

    _ = f == f

    _ = t == t

    _ = a == a

    _ = nil == nil    

    _ = s == interface{}(nil)

    _ = m == interface{}(nil)

    _ = f == interface{}(nil)

// 这些比较编译都没问题。

    _ = s == nil

    _ = m == nil

    _ = f == nil

    _ = 123 == interface{}(nil)

    _ = true == interface{}(nil)

    _ = "abc" == interface{}(nil)

}


3、两个值是如何进行比较的?

假设两个值可以相互比较,并且它们的类型同为T。 (如果它们的类型不同,则其中一个可以转换为另一个的类型。这里我们不考虑两者均为类型不确定值的情形。)

(1)如果T是一个布尔类型,则这两个值只有在它们同为true或者false的时候比较结果才为true。

(2)如果T是一个整数类型,则这两个值只有在它们在内存中的表示完全一致的情况下比较结果才为true。

(3)如果T是一个浮点数类型, 则这两个值只要满足下面任何一种情况,它们的比较结果就为true:

        它们都为+Inf;

        它们都为-Inf;

        它们都为-0.0或者都为+0.0。

        它们都不是NaN并且它们在内存中的表示完全一致。

(4)如果T是一个复数类型,则这两个值只有在它们的实部和虚部均做为浮点数进行进行比较的结果都为true的情况下比较结果才为true。

(5)如果T是一个指针类型(类型安全或者非类型安全),则这两个值只有在它们所表示的地址值相等或者它们都为nil的情况下比较结果才为true。

(6)如果T是一个通道类型,则这两个值只有在它们引用着相同的底层内部通道或者它们都为nil时比较结果才为true。

(7)如果T是一个结构体类型,则它们的相应字段将逐对进行比较。只要有一对字段不相等,这两个结构体值就不相等。

(8)如果T是一个数组类型,则它们的相应元素将逐对进行比较。只要有一对元素不相等,这两个结构体值就不相等。

(9)如果T是一个接口类型,请参阅两个接口值是如何进行比较的。(两个接口值的比较结果只有在下面两种任一情况下才为true)

         这两个接口值都为nil接口值    

        这两个接口值的动态类型相同、动态类型为可比较类型、并且动态值相等。

(10)如果T是一个字符串类型,请参阅两个字符串值是如何进行比较的。

请注意,动态类型均为同一个不可比较类型的两个接口值的比较将产生一个恐慌。比如下面的例子:

相关文章

  • go笔记 - 赋值和值比较规则

    1、赋值规则 赋值可以看作是隐式类型转换 赋值语句中的目标值必须为一个可寻址的值、一个映射元素表达式或者一个空标识...

  • go和python的深浅拷贝理解

    go深拷贝, 就是拷贝值 go浅拷贝, 拷贝引用 go中赋值就能实现拷贝,针对引用类型(slice,map,cha...

  • go语言中值拷贝的成本

    在go语言中,值拷贝是常有的事情。赋值,传参和发送值给channel都有值拷贝。本文将讨论各种类型的值拷贝成本。 ...

  • ES6学习之路02——数组的解构赋值

    解构赋值 解构赋值的规则 只要等号右边的值不是对象或数组,就先将其转为对象,由于undefined和null无法转...

  • Go 基础

    go 介绍 编程 变量赋值初始化 Println 与 Printf 的区别 匿名变量,Go函数可以返回多个值 常量...

  • ES6学习笔记(二)解构赋值

    1、数组的解构赋值 解构:从数组和对象中提取值,对变量进行赋值解构赋值的规则:只要等号右边的值不是对象或数组,就先...

  • 合集 | Go 语言学习笔记目录

    Go 学习笔记 01 | 输出、变量、常量、命名规则和代码风格[https://wonzwang.blog.csd...

  • golang使用技巧

    golang map赋值是引用拷贝 返回值 可以放入一行中 go tools 里面支持vscode跳转 go语言c...

  • ES6笔记(解构赋值)

    ES6笔记(解构赋值) 解构赋值 变量的解构: 解构赋值允许指定默认值。 解构赋值必须保证赋值方 被赋值方类型一...

  • go引用类型

    go引用类型 值类型   go语言中的赋值操作都是值传递,也就是会将变量完整的复制一份,一般的解决思路是使用指针 ...

网友评论

      本文标题:go笔记 - 赋值和值比较规则

      本文链接:https://www.haomeiwen.com/subject/ywblpktx.html