Contents

Go 基本数据类型

1. 整型

整形可细分为两种,有符号整型无符号整型。Go 为整型变量提供了 4 种 size,分别占用 1,2,4 和 8 字节的内存空间。

1
2
int8 int16 int32 int64
uint8 uint16 uint32 uint64

此外,还有两种更常用的整型变量(intuint),但它们所占用的内存大小是不确定的,依赖运行程序的操作系统位数。

2. 浮点型

浮点数只有两种类型:float32 和 float64。

3. 布尔类型

布尔类型在 Go 种是专门的一种类型,两种取值:truefalse

布尔类型和数值类型之间没有隐式转换,不能像 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

字符串不能进行修改,这使得多个字符串对象共享底层内容非常安全。

./1.png

当遇到中英混合的字符串时,这么处理就会出现问题,需要通过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)