go类型转换、赋值和比较
一、转换规则
类型转换涉及到数据的底层类型,常规来说,底层类型相同才可以类型转换,那么如何查看一个类型的底层类型?
方法:对类型进行溯源,碰到无名类型则溯源结束,比如:
type num int
type A []num
type B map[num]string
type C A
// C -> A -> []num , 因为[]num已经是无名类型,不再进行溯源
// B -> map[num]string, map[num]string也是无名类型
var s = []int{1, 2, 3}
_ = C(s) // 这里会报错,因为s和C的底层类型不同
当指针类型转换时,判断的时指针所指向类型(即基类型)的底层类型是否相同,相同则可以转换, 且需要用指针的形式转换,如:
type num int
type A *num
var i int = 10
var p *int = &i
// var a A = A(p) // 这样写会报错
var a A = (*num)(p)
二、赋值规则
赋值可以看作是隐式类型转换,且赋值语句中的目标值必须为一个可寻址的值、一个映射元素表达式或者一个空标识符。
- 赋值中源值的直接部分被赋给了目标值
- 函数传参和结果返回其实都是赋值
三、比较
(1) 基本类型
bool
int
数字
比较值的大小
(2) 复合类型
array
struct
逐个元素或者字段比较,元素或者字段必须为可比较类型
(3) 引用类型
普通变量的引用类型&val:比较地址是否相同
chan: 比较地址是否相同
slice:不可笔记,只能与nil比较
map: 不可比较,只能与nil比较
(4)interface{}类型
比较动态类型和动态值,且都是可比较类型才行
(5) 函数
函数作为一等公民,不能相互比较, 可以与nil比较
(6) slice和map的特殊比较
- []byte类型的slice,使用byte包提供的比较函数
bytes.Equal(slice1, slice2) - 使用反射reflect.DeepEqual可以比较任意的类型
- google的cmp包也可以比较