基本数据类型
Go 里最常用的基本类型就这几类:整数、浮点、复数、布尔、字符串。字符没有独立的 char,用 byte / rune 表示。
整数型
整数按「有没有符号」和「占多少 bit」拆开:
| 类型 | 含义 |
|---|---|
int8 / int16 / int32 / int64 | 有符号,多一位用来存正负 |
uint8 / uint16 / uint32 / uint64 | 无符号,只能存 ≥ 0 |
int / uint | 平台相关,64 位机器上通常是 64 bit |
byte | uint8 的别名 |
rune | int32 的别名,用来表示一个 Unicode 码点 |
记这几条就够用:
- 字面量不写类型时,整数默认是
int。 - 名字带
u就是无符号。 - 后面的数字是二进制位数。
uint8是 8 bit,也就是 1 字节。 int/uint的宽度看机器,不要假定它永远是 32 或 64。
范围可以按位数算。uint8 8 位全存数据:0~2⁸-1,也就是 0~255。int8 要留 1 位给符号,有效是 7 位:-2⁷~2⁷-1,也就是 -128~127。减 1 是因为 0 也占一个编码,和「一小时 60 分钟、分钟只到 59」是同一类边界。
var a uint8 = 2
var b int8 = 2
var c int = 2
go
64 位机器上,int 的上限和 int64 一样:2⁶³-1 = 9223372036854775807。再大一号,编译器会报溢出。
不同类型的整数不能直接相加,要先转换:
var x int32 = 1
var y int64 = 2
// fmt.Println(x + y) // 编译错误
fmt.Println(int64(x) + y)
go
浮点型
只有 float32 和 float64。上限在 math 包里:
math.MaxFloat32大约3.4e38math.MaxFloat64大约1.8e308
字面量不写类型时,默认是 float64。日常计算用 float64 即可,精度更稳。
package main
import (
"fmt"
"math"
)
func main() {
var f = 1.25 // float64
fmt.Printf("%T %.2f\n", f, f)
fmt.Println(math.MaxFloat32)
}
go
浮点有精度误差,比较相等时不要直接 ==,后面写判断再细说。
复数是 complex64 / complex128,字面量写成 1+2i。一般用得少。
字符型
这里说的是单个字符,不是字符串。
- 单引号:
'a'、'中' byte:一个字节,够放 ASCIIrune:一个 Unicode 码点,中文、emoji 用它
字符在 Go 里本质是整数。Println 打出来的是码值;要用 %c 才显示成字符。
package main
import "fmt"
func main() {
var c1 = 'a'
var c2 = 97
fmt.Println(c1, c2) // 97 97
fmt.Printf("%c %c\n", c1, c2) // a a
var r rune = '中'
fmt.Printf("%c %d\n", r, r)
}
go
因为是整数,字符可以做加减:'a' + 1 得到 'b'。
字符串类型
字符串用双引号,字符用单引号:
var s string = "槿"
fmt.Println(s)
go
字符串是不可变的 UTF-8 字节序列。len(s) 是字节数,不是「看见几个字」。中文一个字通常 3 个字节,按字遍历要用 range 或转成 []rune。
转义字符
双引号字符串里,反斜杠表示转义:
| 写法 | 含义 |
|---|---|
\n | 换行 |
\t | 制表符 |
\r | 回到行首 |
\" | 双引号 |
\\ | 反斜杠本身 |
fmt.Println("槿\t笔记")
fmt.Println("第一行\n第二行")
fmt.Println("\"带引号\"")
fmt.Println("C:\\go\\bin")
go
多行字符串
反引号包起来的是原始字符串:换行原样保留,里面的 \n、\t 不会被转义。
package main
import "fmt"
func main() {
s := `今天
天气
真好
`
fmt.Println(s)
}
go
路径、正则、一大段原文,用反引号更省事。
布尔类型
只有 true 和 false。零值是 false。
var ok bool
fmt.Println(ok) // false
go
Go 不允许把整数当成布尔,也不让布尔参与加减或和别的类型互转:
// if 1 { } // 不行
// var b bool = 1 // 不行
// fmt.Println(true + 1) // 不行
go
条件只能写真正的布尔表达式。
零值问题
只声明、不赋值,变量落到该类型的零值:
| 类型 | 零值 |
|---|---|
| 整数 | 0 |
| 浮点 | 0 |
| 字符串 | "" |
| 布尔 | false |
package main
import "fmt"
func main() {
var a int
var b float32
var c string
var d bool
fmt.Printf("%#v\n", a) // 0
fmt.Printf("%#v\n", b) // 0
fmt.Printf("%#v\n", c) // ""
fmt.Printf("%#v\n", d) // false
}
go
%#v 会按 Go 语法打印,空字符串能看出是 "",不会被当成「什么都没打」。