Go的基本类型及其字面量

本文翻译自Basic Types And Basic Value Literals

类型可以被看作是值的模版,而值可以被看成是类型的实例。本文将介绍Go中内置的基本类型及其字面量。本文不介绍复杂类型。

内置类型

Go中内置了以下基本类型:

  • 一个内置的布尔类型:bool
  • 11个内置的整数数字类型:int8, uint8, int16, uint16, int32, uint32, int64, uint64, int, uintuintptr
  • 两个内置的浮点数类型:float32float64
  • 两个内置的复数类型:complex64complex128
  • 一个内置的字符串类型:string

17种内置基本类型中的每一种都属于Go中的一种不同类型。我们可以在代码中使用上面的内置类型而不需要导入任何包,尽管这些类型的所有名称都是非导出标识符。

17种内置基本类型种的15种是数字类型。数字类型包括整数类型,浮点数类型和复数类型。

Go还支持两种内置的别名类型:

  • byte是内置类型uint8的别名。我们可以将byteuint8视为相同的类型。
  • rune是内置类型int32的别名。我们可以将runeint32视为相同的类型。

名称以u开头的整数类型是无符号类型。无符号类型的值始终为非负数。类型名称中的数字表示该类型的值在运行时将占用内存的二进制位数。例如,uint8的每个值占用内存中的8位。因此最大的uint8值是255(),最大的int8的值是127 (),最小的int8值是-128()。

如果一个值占用内存中的N位,我们说该值的大小是N位。类型的所有值的大小始终相同,因此值的大小通常称为类型大小。

我们经常根据类型在内存中占用的字节数来测量值的大小。,一个字节包含8位。所以uint32类型的大小是四个字节。

内存中intuint值的大小取决于操作系统:32位或64位。uintptr值的大小必须足够大,以存储任何内存地址的未解释位。

complex64类型的实部和虚部都是float32类型的值,而complex128类型的实部和虚部都是float64类型的值。

在内存中,Go中的所有浮点数值都以IEEE-754格式存储。

布尔值代表真值。内存中只有两个可能的布尔值,它们由两个预先声明的命名常量表示,falsetrue

逻辑上,字符串表示一段文本。在存储器中,字符串的值存储为字节序列,该字节序列是由字符串值表示的文本片段的UTF-8编码表示。

虽然布尔类型和字符串类型只有一个内置类型,但我们可以定义自定义的布尔类型和字符串类型,并为内置布尔类型和字符串类型声明别名,所以可以有很多布尔和字符串类型。对于任何数字类型也是如此。以下是一些类型声明示例,在这些声明中,单词type是关键字。

// Some type definition declarations.
type status bool     // status and bool are two different types.
type MyString string // MyString and string are two different types.
type Id uint64       // Id and uint64 are two different types.
type real float32    // real and float32 are two different types.

// Some type alias declarations.
type boolean = bool // boolean and bool denote the same type.
type Text = string  // Text and string denote the same type.
type U8 = uint8     // U8, uint8 and byte denote the same type.
type char = rune    // char, rune and int32 denote the same type.

我们可以认为上面定义的自定义real和内置的float32都是float32类型。注意,上一个句子中的第二个float32单词指的是通常所说的浮点数类型,而第一个单词指的是Go中的内置类型。类似的,MyStringstring都是字符串类型,statusbool都是布尔类型。

零值

每种类型都有其对应的零值。类型的零值可以视为类型的默认值:

  • 布尔类型的零值是false
  • 数字类型的零值是0,但不同数字类型的零可能在内存中具有不同的位数。
  • 字符串类型的零值是空字符串

基本类型的字面量

值的字面量是代码中值的文字表示。一个值可能存在多种字面量表示。

表示基本类型值的文本称为基本字面量。基本字面量也被称为字面量常量或未命名常量。

Boolean 字面量

Go规范没有定义布尔字面量。但是,在一般编程中,我们可以将两个预先声明的标识符falsetrue视为布尔字面量。但我们应该知道,严格来说,这两者并不是字面量值。

如上所述,布尔类型的零值用预先声明的false常量表示。

整型字面量

有三种整型字面量表示形式:十进制,八进制和十六进制。例如,以下三个整型字面量都表示十进制的15

0xF // the hex form (must start with a "0x" or "0X")
017 // the octal form (must start with a "0")
15  // the decimal form (mustn't start with a "0")

以下程序会打印出两个true

package main

func main() {
    println(15 == 017) // true
    println(15 == 0xF) // true
}

通常,整数类型的零值在字面量中表示为0,尽管对于整数零值存在许多其他合法的字面量,例如000x0。事实上,这篇文字中为其他类型的数字类型引入的零值字面量也可以表示任何整数类型的零值。

浮点数字面量

一个浮点类型字面量可以包含一个整数部分,小数点,一个小数部分和一个指数部分。某些部分可以省略。例如:

1.23
01.23 // == 1.23
.23
1.
// A "e" or "E" starts the exponent part.
1.23e2  // == 123.0
123E2   // == 12300.0
123.E+2 // == 12300.0
1e-1    // == 0.1
.1e0    // == 0.1
0e+5    // == 0.0

浮点类型的零值的标准字面量是0.0,尽管还有许多其他的合法字面量,例如0.00e0等等。事实上,这篇文章中介绍的其他数字类型的零值字面量也可以表示任何浮点类型的零值。

虚数字面量

一个虚数字面量由浮点数或十进制整数字面量组成,后面跟小写字母i,例如:

1.23i
1.i
.23i
123i
0123i   // == 123i
1.23E2i // == 123i
1e-1i

虚数字面量用来表示一个复数字面量的虚数部分。以下是一些复数字面量:

1 + 2i       // == 1.0 + 2.0i
1. - .1i     // == 1.0 + -0.1i
1.23i - 7.89 // == -7.89 + 1.23i
1.23i        // == 0.0 + 1.23i

复数类型的标准零值字面量是0.0+0.0i,也有许多其他的合法字面量,例如:0i.0i0+0i

Rune 字面量

Rune类型,包括自定义rune类型和内置rune类型,是一种特殊的整数类型,因此所有的rune类型值都可以用上面介绍的整数字面量表示。另一方面,各种整数类型的值也可以用下面介绍的rune字面量来表示。

一个rune值用于存储一个Unicode码点。通常,一个Unicode字符包含一个字节,但我们也应该知道,某些Unicode字符由多余一个的字节组成。

Rune字面量表示为一个单引号中包含的一个或多个字符。由单引号括起来的字符表示一个Unicode码点。rune字面量有一些变体,最流行的rune字面量只是用两个单引号括起来的字符,例如:

'a' // an English character
'π'
'众' // a Chinese character

以下的rune字面量等同于字符'a'(字符a的Unicode值是97)

'\141'   // 141 is the octal representation of decimal number 97
'\x61'   // 61 is the hex representation of decimal number 97
'\u0061'
'\U00000061'

请注意,\后面必须有正好三个八进制数字来表示一个字节值,\x后面必须正好跟着两个十六进制数字来表示一个字节值,\u后面必须正好跟着四个十六进制数字来表示一个rune值,\U后面必须正好跟着八个十六进制数字来表示一个rune值。每个这样的八进制或十六进制数字序列必须代表合法的Unicode码点,否则无法编译。

以下程序会打印出7个true

package main

func main() {
    println('a' == 97)
    println('a' == '\141')
    println('a' == '\x61')
    println('a' == '\u0061')
    println('a' == '\U00000061')
    println(0x61 == '\x61')
    println('\u4f17' == '众')
}

事实上,刚刚提到的四种变体rune字面量形式在实践中很少用于表示rune值。它们偶尔用于可解析的字符串字面量(详见下一小节)。

如果一个rune字面量由两个字符组成(不包括两个引号),其中第一个字符是\而第二个字符不是一个数字,或者不是xuU,那么这两个连续的字符将作为一个特殊的转义字符。要转义的可能字符对是:

\a   (Unicode value 0x07) alert or bell
\b   (Unicode value 0x08) backspace
\f   (Unicode value 0x0C) form feed
\n   (Unicode value 0x0A) line feed or newline
\r   (Unicode value 0x0D) carriage return
\t   (Unicode value 0x09) horizontal tab
\v   (Unicode value 0x0b) vertical tab
\\   (Unicode value 0x5c) backslash
\'   (Unicode value 0x27) single quote

\n是最常用的转义字符对。例如:

    println('\n') // 10
    println('\r') // 13
    println('\'') // 39

    println('\n' == 10)     // true
    println('\n' == '\x0A') // true

rune类型的零值字面量具有多种形式,例如\000\x00\u0000等等。事实上,我们也可以使用上面介绍的任意数字类型字面量来表示rune类型,如00x00.00e00i等。

字符串字面量

字符串类型的值在Go中使用UTF-8编码。事实上,所有Go的源代码文件必须兼容UTF-8编码。

有两种形式的字符串字面量,可解析的字符串字面量(双引号形式)和原生字符串字面量(反引号形式)。例如,以下两个字符串字面量是等效的:

// The interpreted form.
"Hello\nworld!\n\"你好世界\""

// The raw form.
`Hello
world!
"你好世界"`

在上例中的可解析字符串字面量,每一个\n字符对将作为一个换行符进行转义,并且每个\"字符对将作为一个双引号字符转义。大多数此类转义字符与rune类型中转义字符一致,除了\"只在字符串字面量中合法,而\'只在rune字面量中合法。

\\x\u\U后跟几个八进制或十六进制数字的字符序列也可用于可解析的字符串字面量。

// The following interpreted string literals are equivalent.
"\141\142\143"
"\x61\x62\x63"
"abc"

// The following interpreted string literals are equivalent.
"\u4f17\xe4\xba\xba" // The Unicode of 众 is 4f17, which is
                     // UTF-8 encoded as three bytes: e4 bc 97.
"\xe4\xbc\x97\u4eba" // The Unicode of 人 is 4eba, which is
                     // UTF-8 encoded as three bytes: e4 ba ba.
"\xe4\xbc\x97\xe4\xba\xba"
"众人"

请注意每一个英语字符包含一个字节,而每一个中文字符包含三个字节。

在原生字符串字面量中,不会转义任何字符序列。反引号字符不允许出现在原生字符串字面量中。为了获得更好的跨平台兼容性,原生字符串字面量中的回车字符(Unicode码点0x0D)将被丢弃。

字符串类型的零值可以被表示为""``

基本字面量的代表性

任何一个字符串字面量都可以表示一个字符串类型都值。

预先声明的falsetrue可以表示表示任何布尔类型都值。但同样,我们应该知道这两个值不是严格意思上但字面量。

只有在不需要舍入时,数字字面量才可用于表示整数值。例如,1.23e2可以表示任意整数类型但值,但是1.23不能。使用数字字面量表示非整数类型的值时,允许舍入。

每种基本数字类型都具有可表示的值范围。因此,如果字面量的值溢出了类型的值范围,则该字面量不能表示为该类型的值。

一些例子:

字面量 可表示的类型
256 int8uint8外的所有数字类型
255 int8外的所有数字类型
-123 除无符号类型外的所有数字类型
123 所有的数字类型
123.000 同上
1.23e2 同上
'a' 同上
1.0+0i 同上
1.23 所有的浮点数和复数类型
0x10000000000000000(16个0) 同上
3.5e38 float32complex64外的所有浮点数和复数类型
1+2i 所有的复数类型
2e+308 无法用基本类型表示

注意

  • 由于0x10000000000000000表示的值超出了Go提供的所有整数类型的表示范围,因此该字面量不能表示为任何整数类型
  • 由于IEEE-754标准的float32类型所能表示的最大数值为3.40282346638528859811704183484516925440e+38,因此3.5e38不能表示float32complex64的值
  • 由于IEEE-754标准的float64类型所能表示的最大数值为1.797693134862315708145274237317043567981e+308,因此2e+308不能表示为float64complex128类型的值
  • 最后请注意,尽管0x10000000000000000可以表示为float32类型的值,但是它不能在内存中精确表示任何float32的值。换句话说,当它用作float32的值时,它将四舍五入到最接近的float32值。

你可能感兴趣的:(Go的基本类型及其字面量)