深色模式
Go语言类型系统
类型的分类
类型分为基本类型和组合类型,这两种类型又可以细分如下:
基本类型:
字符串
string
布尔
bool
数值(15种)
int8
uint8
(byte
)int16
uint16
int32
(rune
)uint32
int64
uint64
int
uint
uintptr
float32
float64
complex64
complex128
注意:byte
和rune
只是类型别名,不是定义类型。
组合类型:
指针
结构体
函数
容器
- 数组
slice
map
通道
channel
接口
interface
非类型安全指针
unsafe.Pointer
综上,一共有26种。
类型声明
类型声明的方式有两种,一种是类型定义声明,另一种是类型别名声明。
类型定义声明
Go
// 定义单个类型。
type NewTypeName SourceType
// 定义多个类型。
type (
NewTypeName1 SourceType1
NewTypeName2 SourceType2
)
注意:
- 一个新定义的类型和它的源类型为两个不同的类型。
- 在两个不同的类型定义中的定义的两个类型肯定为两个不同的类型。
- 一个新定义的类型和它的源类型的底层类型一致并且它们的值可以相互显式转换。
- 类型定义可以出现在函数体内。
类型别名声明
Go
type (
Name = string
Age = int
)
type table = map[string]int
type Table = map[Name]Age
注意:
- 类型别名和等号右边的类型是同一类型。
- 类型别名声明也可以出现在函数体内。
定义类型与非定义类型
一个定义类型是一个类型定义声明中定义的类型。
所以,基本类型都是定义类型。
有几个名词:
定义类型、有名类型、命名类型,表示同一意思;
非定义类型、无名类型、非命名类型,表示同一意思。
再结合基本类型与组合类型,总结如下:
基本类型都是定义类型。
组合类型中,有定义类型,也有非定义类型。
例:
Go
type IntSlice []int // IntSlice是一个定义类型
var a []int // a的类型是非定义类型,
底层类型
底层类型的规则
- 一个内置类型的底层类型为它自己。
unsafe
标准库包中定义的Pointer
类型的底层类型是它自己。- 一个非定义类型的底层类型为它自己。
- 在一个类型声明中,新声明的类型和源类型共享底层类型。
例
Go
// 这四个类型的底层类型均为内置类型int。
type (
MyInt int
Age MyInt
)
// 下面这三个新声明的类型的底层类型各不相同。
type (
IntSlice []int // 底层类型为[]int
MyIntSlice []MyInt // 底层类型为[]MyInt
AgeSlice []Age // 底层类型为[]Age
)
// 类型[]Age、Ages和AgeSlice的底层类型均为[]Age。
type Ages AgeSlice
如何溯源一个类型的底层类型?
规则很简单,在溯源过程中,当遇到一个内置类型或者非定义类型时,溯源结束。
上例中的溯源过程如下:
MyInt → int Age → MyInt → int IntSlice → []int MyIntSlice → []MyInt → []int AgeSlice → []Age → []MyInt → []int Ages → AgeSlice → []Age → []MyInt → []int
注意
- 底层类型为内置类型
bool
的类型称为布尔类型; - 底层类型为任一内置整数类型的类型称为整数类型;
- 底层类型为内置类型
float32
或者float64
的类型称为浮点数类型; - 底层类型为内置类型
complex64
或complex128
的类型称为复数类型; - 整数类型、浮点数类型和复数类型统称为数字值类型;
- 底层类型为内置类型
string
的类型称为字符串类型。
底层类型的概念,关系到类型转换、赋值和类型比较规则。