基本数据
整数
-
GO同时具备有符号整数和无符号整数
- 有符号整数分四种大小:8位、16位、32位、64位,用int8、int16、int32、int64表示
- 对应的无符号整数是uint8、uint16、uint32、uint64
- 此外还有两种类型int和uint。在特定平台上,其大小与原生的有符号整数\无符号整数类型大小相等
- rune类型是int32类型的同义词,这两个名称可以互换使用。同样byte类型是int8类型的同义词,强调一个值是原始数据而非量值
- uintptr也是一种无符号整数,其大小不确定,但足以完整存放指针。主要用于底层编程,例如Go与C的接口程序
-
二元运算符的优先级排序
* / % << >> & &^ + - | ^ == != < <= > >= && ||分五大优先级
浮点数
- Go具有两种大小的浮点数float32和float64,在math包中有这两个类型的最大值和最小值MaxFloat32、MaxFloat64
- 浮点数可以通过
Printf的谓词%g输出,或者也可以使用%e(有指数)或%f(无指数)来输出 - math包中具有NaN(Not a Number),它表示数学上无意义的运算结果(如
0/0),在数学运算中,我们倾向于将NaN作为一个信号值,但直接判断具体的计算结果是否为NaN可能会造成潜在错误,因为与NaN的比较总是不成立的(除了!=)
复数
-
Go具有两种类型的复数complex64、complex128,二者分别由float32和float64构成。内置的complex函数根据给定的实部和虚部创建复数,而内置的real函数和imag函数则分别提取复数的实部和虚部:
var x complex128 = complex(1, 2) // 1+2i var y complex128 = complex(3, 4) // 3+4i fmt.Println(x * y) // "-5+10i" fmt.Println(real(x * y)) // "-5" fmt.Println(imag(x * y)) // "10" -
如果在浮点数或十进制整数后面紧接着写字母i,如2i,它就变成一个虚数,表示一个实部为0的复数,根据常量运算规则,复数常量可以和其他常量相加。
x := 1 + 2i y := 3 + 4i -
math/cmplx包提供了复数运算所需的库函数,例如复数的平方根函数和复数的幂函数
fmt.Println(cmplx.Sqrt(-1)) // "(0+1i)"
布尔值
- bool型的值或布尔值(boolean)只有两种可能:真(true)和假(false)
- bool类型无法隐式转换为数值(0或1),反之也不行
字符串
-
字符串是不可变的字节序列,它可以包含任意数据,包括0值字节
-
不可变意味着两个字符串能安全地共用同一段底层内存,使得复制任何长度字符串的开销都低廉,例如
s := "hello world" hello := s[:5] // hello world := s[6:] // world这里去获取s、hello、world的&s、&hello、&world,会发现他们的地址还是不同的。这是因为,Go中string的内存模型如下所示
使用&s取到的地址只是string这个结构体的地址,并非底层内存的地址,这里通过反射可以获取到该地址。
s := "hello world" hello := s[:5] // hello world := s[6:] // world fmt.Printf("s %v \n", (*reflect.StringHeader)(unsafe.Pointer(&s)).Data) fmt.Printf("hello %v \n", (*reflect.StringHeader)(unsafe.Pointer(&hello)).Data) fmt.Printf("world %v \n", (*reflect.StringHeader)(unsafe.Pointer(&world)).Data) // out // s 5006394 // hello 5006394 // world 5006400可以看到,hello和s内部指针指向的地址是相同的,他们是共用的一段内存地址
-
通过s[i]可以访问到第i个字符,试图访问许可范围外的字节会触发宕机异常
-
s[i:j]可以生成一个新的字符子串
-
字符串可以通过运算符做比较,如==和<;比较运算按字节进行,结果服从本身的字典排序
字符串字面量(string literal)
-
字符串的值可以直接写成字符串字面量(string literal),形式上就是带双引号的字节序列:"Hello, 世界"
-
因为Go的源代码总是按UTF-8编码,并且习惯上Go的字符串会按UTF-8解读,所以在源码中我们可以将Unicode码点写入字符串字面量
-
转移字符
\a “警告”或响铃 \b 退格符 \f 换页符 \n 换行符(指直接跳到下一行的同一位置) \r 回车符(值返回本行行首)会清除本行的内容// 例如 fmt.Println("hello\rgo") // 输出:go\t 制表符 \v 垂直制表符 \' 单引号(仅用于文字字符字面量'\'') \" 双引号 \\ 反斜杠 \xhh 十六进制的转义字符,h是十六进制数字(大小写皆可),且必须是两位。 \ooo 八进制的转义字符,必须使用三位八进制数字(0~7),且不能超过\377
Unicode
- 在Go中使用rune来代表Unicode字符记号,这是一个int32类型的数据
UTF-8
字符串和字节slice
- 四个标准包对字符串操作特别重要:bytes、strings、strconv、unicode
- strings包提供了许多函数,用于搜索、替换、比较、修整、切分和连接字符串
- bytes包也有类似的函数,用于操作字节slice
- strconv包具备的函数,主要用于转换布尔值、整数、浮点数为与之对应的字符串形式,或者将字符串转化为布尔值、整数、浮点数
- Unicode包有判别文字符号值特性的函数,如IsDigit、IsLetter、IsUpper、IsLower。转换函数ToUpper、ToLower将其转换成指定的大小写
常量
-
使用 const 关键字来定义
const pi = 3.14159 // 近似值;math.Pi是更准确的近似
常量生成器iota
-
常量的声明可以使用常量生成器iota来生成,它创建一系列相关值,而不是逐个显式的写出。从0开始取值,逐项加1
type Weekday int const ( Sunday Weekday = iota Monday Tuesday Wednesday Thursday Friday Saturday )const ( _ = 1 << (10 * iota) KiB // 1024 = 1 << 10 MiB // 1048576 = 1 << 100 GiB // 1073741824 = 1 << 1000 TiB // PiB EiB ZiB YiB )
无类型常量
-
Go中的许多常量并不从属某一具体类型,编译器将这些从属类型待定的常量表示成某些值,这些值比基本类型的数字精度更高,且算数精度高于原生的机器精度。借助推迟确定从属类型,无类型常量不仅能暂时维持更高的精度,与类型已确定的常量相比,它们还能写进更多表达式而无需转换类型。例如:
fmt.Println(YiB/ZiB) // 1024