1. 整型
整形可细分为两种,有符号整型和无符号整型。Go 为整型变量提供了 4 种 size,分别占用 1,2,4 和 8 字节的内存空间。
1
2
|
int8 int16 int32 int64
uint8 uint16 uint32 uint64
|
此外,还有两种更常用的整型变量(int
和uint
),但它们所占用的内存大小是不确定的,依赖运行程序的操作系统位数。
2. 浮点型
浮点数只有两种类型:float32 和 float64。
3. 布尔类型
布尔类型在 Go 种是专门的一种类型,两种取值:true
和false
。
布尔类型和数值类型之间没有隐式转换,不能像 C 语言那样把数值类型当作条件逻辑使用。
1
2
3
4
|
a := 1
if a { // non-boolean condition in if statement
fmt.Println("Integer as bool")
}
|
也不能显示类型转换。
1
2
3
4
|
a := 1
if bool(a) { // cannot convert a (variable of type int) to type bool
fmt.Println("Integer as bool")
}
|
必要时只能这么恶心一下。
1
2
3
4
5
6
7
8
9
10
11
12
|
// bool to integer
func btoi(b bool) int {
if b {
return 1
}
return 0
}
// integer to bool
func itob(i int) bool {
return i != 0
}
|
4. 字符串
字符串是一种特殊的切片类型,语意上可以看成由 Unicode 码点(rune
)构成的序列。从底层来看,只是字节类型构成的序列。
rune
在底层是 uint32;byte
在底层是 uint8。单独创造两种类型是为了在语义上更加明确。
Go 的字符串采用的是UTF-8
变长编码,简单来说,一个英文字符占 1 字节,中文字符占 3 字节。
字符串的一些操作都是面向底层的byte
来完成的。
1
2
3
4
5
6
|
s := "hello, world!"
fmt.Println(len(s)) // 13 bytes
fmt.Println(s[0], s[4]) // 'h' and 'o'
fmt.Println(s[0:5]) // "hello", with s[0] included, s[5] excluded
|
字符串不能进行修改,这使得多个字符串对象共享底层内容非常安全。
当遇到中英混合的字符串时,这么处理就会出现问题,需要通过rune把视角转换为 Unicode 码点。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
s := "hello你好"
for i := 0; i < len(s); i++ { // len == 11
fmt.Printf("%c", s[i]) // helloä½ å¥½
}
runes := []rune(s)
for i := 0; i < len(runes); i++ { // len == 7
fmt.Printf("%c", runes[i]) // hello你好
}
// 直接通过 range
for _, r := range s {
fmt.Printf("%c", r) // hello你好
}
// import "unicode/utf8"
rune_len := utf8.RuneCountInString(s)
fmt.Println(rune_len) // 7
|
4.1 Raw string
Raw string 不会对内容做任何转义,几乎是所见即所得,常用来表示一些特定场景下的文本内容。例如,HTML。
1
2
3
4
5
6
7
|
rawS := `**\t\n
**`
fmt.Println(rawS)
Output:
**\t\n
**33
|
5. 类型转换
5.1 整数浮点之间转换
本质上都属于数值型,可以直接转换,只是可能会有精度损失或溢出的问题。
1
2
3
4
5
6
7
8
|
var a int32 = 128
var b int8 = int8(a) // 溢出
var c int64 = int64(a) // ok
fmt.Println(a, b, c) // 128 -128 128
var f float32 = 1.234
var d int8 = int8(f)
fmt.Println(f, d) // 1 1.234
|
5.2 数字与字符串互转
以整数为例,小数及其它类型查阅 api 可知。
5.2.1 integer to string
1
2
3
|
x := 123
y := fmt.Sprintf("%d", x)
z := strconv.Itoa(x)
|
以不同进制转换。
1
2
3
|
// func FormatInt(i int64, base int) string
x := 27
s := strconv.FormatInt(int64(x), 2) // "11011"
|
5.2.2 string to integer
1
2
3
|
n, err := strconv.Atoi("1234");
// ParseInt(s string, base int, bitSize int) (i int64, err error)
m, err := strconv.ParseInt("1234", 10, 32)
|
5.3 字符串转字节序列
字符串是不可修改的,如果需要对其中的某个字符进行修改,通常是转为 byte 切片,完成修改后再转换回来。如果字符串种包含中文字符,就转为 rune 切片。
1
2
3
|
s := "hello"
b := []byte(s)
s2 := string(b)
|