基本内置类型
下表是go语言内置的基本类型。
关键字 | 描述 | 占用内存(字节) | 类型转换 |
---|---|---|---|
bool | 布尔类型(只有true和false两个值) | 1 | 不支持 |
int8 | 有符号8位整型 | 1 | 支持 |
uint8 | 无符号8位整型,别名byte | 1 | 支持 |
int16 | 有符号16位整型 | 2 | 支持 |
uint16 | 无符号16位整型 | 2 | 支持 |
int32 | 有符号32位整型,别名rune | 4 | 支持 |
uint32 | 无符号32位整型 | 4 | 支持 |
int64 | 有符号64位整型 | 8 | 支持 |
uint64 | 无符号64位整型 | 8 | 支持 |
int | 有符号整型 | 依赖编译器实现 | 支持 |
uint | 无符号整型 | 依赖编译器实现 | 支持 |
uintptr | 无符号整型,保存地址 | 编译器必须保证uintptr类型的值的尺寸能够存下任意一个内存地址 | 支持 |
float32 | 单精度浮点型 | 4 | 支持 |
float64 | 双精度浮点型 | 8 | 支持 |
complex64 | 实部和虚部都是float32类型的值 | 8 | 支持 |
complex128 | 实部和虚部都是float64类型的值 | 16 | 支持 |
string | 字符串类型 | 占用大小由字符串本身决定 | 支持 |
表中特地强调了类型是否支持类型转换,这是因为go语言对类型要求是非常严格的,是真正的强类型语言。一个具体的例子如下所示:
代码语言:javascript复制package main
import "fmt"
func main() {
var a = 123 // int类型
var b = 1.3 // float64类型
var c = b * float64(a) // 尽管a和b都是数值类型,但是由于它们一个是int类型,另一个是float64类型,go不允许它们之间进行运算,因此必须做类型转换。
fmt.Println(c)
}
这在C ,Python中都是不需要显式的类型转换。而在go语言中,哪怕它们都是数字,但是其基本类型不一致,就必须经过显式的类型转换才能进行运算。
type关键字
type关键字可以用来定义类型或者声明类型别名。下面是一些例子:
代码语言:javascript复制// 一些类型定义声明
type status bool // status和bool是两个不同的类型
type MyString string // MyString和string是两个不同的类型
type Id uint64 // Id和uint64是两个不同的类型
type real float32 // real和float32是两个不同的类型
// 一些类型别名声明
type boolean = bool // boolean和bool表示同一个类型
type Text = string // Text和string表示同一个类型
type U8 = uint8 // U8、uint8和 byte表示同一个类型
type char = rune // char、rune和int32表示同一个类型
var aa boolean = false
var bb status = false
fmt.Printf("type:%Tn", aa) // 输出type:bool
fmt.Printf("type:%Tn", bb) // 输出type:main.status
在go语言buildin.go中就可以看到byte,any,rune是类型别名,而其余类型则是类型定义。
零值
每种类型都有一个零值。一个类型的零值可以看作是此类型的默认值。
代码语言:javascript复制一个布尔类型的零值表示真假中的假。
数值类型的零值都是零(但是不同类型的零在内存中占用的空间可能不同)。
一个字符串类型的零值是一个空字符串。
字面值常量
- 一个字符串字面量的默认类型是预声明的string类型。
- 一个布尔字面量的默认类型是预声明的bool类型。
- 一个整数型字面量的默认类型是预声明的int类型。
- 一个rune字面量的默认类型是预声明的rune(亦即int32)类型。
- 一个浮点数字面量的默认类型是预声明的float64类型。
- 如果一个字面量含有虚部字面量,则此字面量的默认类型是预声明的complex128类型。
整数类型字面量
整数类型支持十六进制,十进制,八进制,二进制的字面量。例如:
代码语言:javascript复制fmt.Println(0xABCDEF) //十六进制字面量,以0x或者0X开头
fmt.Println(01234567) //八进制字面量,以0开头
fmt.Println(0o1234567) //八进制字面量,go1.13之后支持以0o或者0O开头的八进制数
fmt.Println(0b010101) //二进制字面量,以0b或者0B开头
浮点数类型字面量
浮点数的字面量可以如下所示:
代码语言:javascript复制println(123.123)
println(.1)
println(1.)
println(-0.0)
println(2e2) // 科学计数法e表示以10为底数,e后面的数值是指数。
println(0x1p2) //go1.13之后支持的十六进制浮点数字面量,p表示以2为底数,p后面的是指数。
println(0x2e2) // 由于e是十六进制的数码,因此0x2e2表示的是十六进制数,而不是2x10^2.
复数类型字面量
由于复数类型的实部和虚部都是浮点数类型,因此复数类型可以如下所示:
代码语言:javascript复制println(1 2i)
println(1.2 3.14i)
println(0 0i)
从Go 1.13开始,下划线_可以出现在整数、浮点数和虚部数字面量中,以用做分段符以增强可读性。例如:
代码语言:javascript复制println(100_0000_0000) //国人习惯于每四个数字一组
println(9_999_999) //外国人习惯于每三个数字一组
rune值的字面量
rune是int32类型的别名,rune是一个特殊的整数类型,在go语言中,一个rune值表示一个Unicode码点。就像是C/C 中的char类型(C/C 支持ASCII编码,一个字节就够表示了,但是go支持UTF-8,一个字节不足以表示Unicode)。一个rune字面量由若干包在一对单引号中的字符组成,包在单引号中的字符序列表示一个Unicode码点值。例如:
代码语言:javascript复制println('a')
println('国')
println('x61') // 61是97的十六进制表示
println('141') // 141是97的八进制表示
println('u0061')
println('U00000061')
之后跟随三个八进制数字字符(0-7)表示一个byte值或者是类似n,t这样的转义字符, x之后必须跟随两个十六进制数字字符(0-9,a-f和A-F)表示一个byte值, u之后必须跟随四个十六进制数字字符表示一个rune值(此rune值的高四位都为0), U之后必须跟随八个十六进制数字字符表示一个rune值。 这些八进制和十六进制的数字字符序列表示的整数必须是一个合法的Unicode码点值,否则编译将失败。 下面这样无效的Unicode码点值将会导致go编译失败。
代码语言:javascript复制println('U99091111') // escape is invalid Unicode code point U 99091111
字符串字面值
在Go中,字符串值是UTF-8编码的。Go字符串的字面量形式有两种。 一种是解释型字面表示(interpreted string literal,双引号风格)。 另一种是直白字面表示(raw string literal,反引号风格)。例如:
代码语言:javascript复制print("123n") // 解释形式(双引号风格)的字符串字面量中,每个n将被转义为一个换行符
print(`123n`) // 直白形式不会将n转义为换行符
前文提到rune类型实际上就是go语言的字符类型,那么理所当然的可以由多个字符组成字符串。例如:
代码语言:javascript复制println("141142143")
println("x61x62x63")
println("U00001111U00002222")
println("uaaaaubbbb")
为了跨平台兼容性,直白反引号风格的字面表示中的回车符(Unicode码点为0x0D) 将被忽略掉。 一个数值型的字面量只有在不需要舍入时,才能用来表示一个整数基本类型的值。 比如,1.0可以表示任何基本整数类型的值,但1.01却不可以。 当一个数值型的字面量用来表示一个非整数基本类型的值时,舍入(或者精度丢失)是允许的。例如:
代码语言:javascript复制var i int32 = 3.0 // 不允许舍入
var f float32 = 0x10000000000000000 //允许精度丢失
println(i)
println(f)
参考资料
https://gfw.go101.org/article/basic-types-and-value-literals.html