Skip to content

Latest commit

 

History

History
49 lines (37 loc) · 2.49 KB

go-spec-properties.md

File metadata and controls

49 lines (37 loc) · 2.49 KB

type/value 的属性

类型标识

两个类型要么相同要么不一样.

新定义的一个类型,和其他类型都是不一样的. 要判断两个类型是否一致,需要判断底层类型的结构是否一致. 其实很简单:底层类型的结构体字面量是否一致,每个字段的对应的类型是否一致.

如何识别两个类型是一样的:

  • 两数组类型相同:表示元素类型和长度都一样
  • 两切片类型相同:表示元素类型一样
  • 两结构体类型相同:表示字段顺序相同,字段的名字/类型/tag都相同
    • 如果是不导出的字段,类型是不同的包,那也是不一样的
  • 两指针类型相同:表示基础类型相同
  • 两函数类型相同:表示参数/返回值的顺序/类型一致(名字没要求),可变参情况一致
  • 两接口类型相同:表示方法集相同(包括里面的函数名和函数类型相同),顺序无所谓
    • 同样的,不导出的方法名来之不同的包,那也是不一样的
  • 两map类型相同:表示key和value的类型相同
  • 两信道类型相同:表示元素类型和方向相同

type a = b 和 type a b 是完全不一样的, 前者是一个别名,a和b本质上是一样的, 后者是新定义一个类型, 我们新定义一个结构体时,是不会用到等号的,因为本意是定义一个新类型, 所以要注意上面特别标明的部分,定义的新类型和所有其他类型都是不同的.

赋值

有个变量b的类型是T,如果要将a赋值给b,要满足以下条件之一即可:

  • a的类型是T
  • a的类型是V,当V和T的底层类型一致,且V和T中至少有一个不是定义类型
    • 在我的测试中,发现VT如果有一个是定义类型,赋值会出错
    • 定义类型的对象作为右值时,会出错,需要显示转换才行
    • 这点估计是spec和实现有差别的地方
  • T是接口,a的类型实现了T
  • a是双向信道,T是信道类型,a的类型是V,VT她们的元素类型相同,且VT至少有一个不是定义类型
  • a是nil,T是指针/函数/slice/map/channel/interface类型
  • b是无类型的常量,值可以转换成类型T

识别常量如何转换成指定类型

我们说某个常量可以表示为某个类型的值,那么这个常量要满足以下条件之一即可:

  • 类型T决定了一系列值的集合,b在这个集合中即可。eg:var i int = 0
  • T是浮点类型,只要b可以转换之后没有溢出即可
  • T是复数类型,b正好可以将实数和虚数转换成T指定的类型(float32/float64)