《Go语言实战笔记》2 类型

161 阅读6分钟

2.1 变量

  • 变量时一段或多段用来存储数据的内存

定义

  • var
  • 类型放在变量名后
  • 运行时内存分配操作会确保变量自动初始化为二进制零值
  • 显示提供初始化值,可省略变量类型,由编译器推断

image.png

  • 可一次定义多个变量,包括用不同初始值定义不同类型

image.png

  • 依照惯例,建议以组方式整理多行变量定义

image.png

简短模式

image.png

  • 限制:
    • 定义变量,同时显示初始化
    • 不能提供数据类型
    • 只能用在函数内部

多变量赋值

  • 在进行多变量赋值操作时,首先计算出所有右值,然后再依次完成赋值操作
  • 复制操作,必须保证左右值类型相同

未使用错误

  • 编译器将未使用局部变量当作错误

2.2 命名

  • 命名建议
    • 以字母或下_线开始,由多个字母、数字和下阃线组合而成。
    • 区分大小写。
    • 使用驼峰(camel case )拼写格式。
    • 局部变量优先使用短名。 ・不要使用保留关键字。
    • 不建议使用与预定义常量、类型、内置函数相同的名字
    • 专有名词通常会全部大写,例如escapeHTML。
  • 尽管Go支持用汉字等Unicode字符命名,但从编程习惯上来说,这并不是好选择
  • 符号名字首字母大小写决定了其作用域。首字母大写的为导出成员,可被包外引用,而 小写则仅能在包内使用。

2.3 常量

  • 量值必须是编译期可确定的字符、字符串、数字或布尔值。可指定常量类型,或由编 译器通过初始化值推断,不支持C/C++数字类型后缀
  • 可在函数代码块中定义常量,不曾使用的常量不会引发编译错误
  • 常量值也可以是某些编译器能计算出结果的表达式,如unsafe.Sizeof、len、cap等

image.png

  • 在常量组中如不指定类型和初始化值,则与上一行非空常量右值(表达式文本)相同

image.png

枚举

  • Go并没有明确意义上的enum定义,不过可借助iota标识符实现一组自增常量值来实现

image.png

image.png

  • 自增作用范围为常量组。可在多常量定义中使用多个iota,它们各自单独计数,只须确 保组中每行常量的列数量相同即可。

image.png

  • 如中断iota自增,则必须显式恢复。且后续自增值按行序递增,而非C enum那般按上 一取值递增。

image.png

  • 自增默认数据类型为int,可显示指定类型

image.png

  • 自增默认数据类型为int,可显式指定类型

image.png

展开

常量不同于变量在运行期分配存储内存(非优化状态),常量通常会被编译器在预处理阶段直接展开,作为指令数据使用。

2.4 基本类型

image.png

image.png

  • 标准库strconv可在不同进制(字符串)间转换

image.png

image.png

别名

在官方的语言规范中,专门提到两个别名

byte    allias for uint8
rune    allias for int32

别名无须转换,可以直接赋值

2.5 引用类型

引用类型特指slice、map、channel这三种预定义类型。

相比数字、数组等类型,引用类型拥有更复杂的存储结构。除分配内存外,它们还须初 始化一系列属性,诸如指针、长度,甚至包括哈希分布、数据队列等。

内置函数new按指定类型长度分配零值内存,返回指针,并不关心类型内部构造和初始 化方式。而引用类型则必须使用make函数创建,编译器会将make转换为目标类型专用的创建函数(或指令),以确保完成全部内存分配和相关属性初始化。

image.png

当然new函数也可为引用类型分配内存,但这是不完整创建。以字典(map) 为例,它仅分配了字典类型本身(实际就是个指针包装)所需内存,并没有分配键值存储内存,也没有初始化散列桶等内部属性,因此它无法正常工作。

2.6 类型转换

隐式转换造成的问题远大于它带来的好处。

除常量、别名类型以及未命名类型外,Go强制要求使用显式类型转换。加上不支持操 作符重载,所以我们总是能确定语句及表达式的明确含义。

如果转换的目标是指针、单向通道或没有返回值的函数类型,那么必须使用括号,以避 免造成语法分解错误。

2.7 自定义类型

使用关键字type定义用户自定义类型,包括基于现有基础类型创建,或者是结构体、函数类型等。

image.png

即便指定了基础类型,也只表明它们有相同底层数据结构,两者间不存在任何关系,属 完全不同的两种类型。 除操作符外,自定义类型不会继承基础类型的其他信息(包括方法)。不能视作别名,不能隐式转换,不能直接用于比较表达式。

image.png

未命名类型

与有明确标识符的bool int string等类型相比,数组、切片、字典、通道等类型与具 体元素类型或长度等属性有关,故称作未命名类型。当然,可用type为其提供具体名称,将其改变为命名类型 具有相同声明的未命名类型被视作同一类型。

  • 具有相同基类型的指针。
  • 具有相同元素类型和长度的数组array。
  • 具有相同元素类型的切片slice。
  • 具有相同键值类型的字典map。
  • 具有相同数据类型及操作方向的通道channel。
  • 具有相同字段序列(字段名、字段类型、标签,以及字段顺序)的结构体 struct。
  • 具有相同签名(参数和返回值列表,不包括参数名)的函数func。
  • 具有相同方法集(方法名、方法签名,不包括顺序)的接口interface。

未命名类型转换规则:

  • 所属类型相同。
  • 基础类型相同,且其中一个是未命名类型。
  • 数据类型相同,将双向通道赋值给单向通道,且其中一个为未命名类型。
  • 将默认值nil赋值给切片、字典、通道、指针、函数或接口。
  • 对象实现了目标接口