数据类型

翻译整理自 A Tour of Go - More types、Language Specification - Types 与 Effective Go - Data。

1. 基本类型

类型 含义 默认零值
bool 布尔 false
string UTF-8 字符串 ""
int / int8 / int16 / int32 / int64 有符号整数 0
uint / uint8 / ... / uintptr 无符号整数 0
byte uint8 别名 0
rune int32 别名(Unicode 码点) 0
float32 / float64 浮点数 0
complex64 / complex128 复数 0

通常直接用 int、uint、float64 即可。

var b bool = true
var s string = "你好"
var f float64 = 3.14
var r rune = '世' // Unicode 码点

2. 字符串

字符串不可变字节序列(默认 UTF-8):

s := "Hello, 世界"
fmt.Println(len(s))            // 13 字节
fmt.Println(utf8.RuneCountInString(s)) // 9 个 rune

for i, c := range s {
    fmt.Printf("%d:%c ", i, c)
}

字符串拼接、模板化:

greeting := "Hello, " + "Go"
formatted := fmt.Sprintf("%s! Today is %s", greeting, "Monday")

类型转换

无隐式转换,需显式:

var i int = 42
var f float64 = float64(i)
var u uint = uint(f)

3. 指针

Go 有指针但没有指针运算(除 unsafe):

x := 10
p := &x          // *int
fmt.Println(*p)  // 10
*p = 20
fmt.Println(x)   // 20

new(T) 返回零值的指针:

p := new(int)
*p = 100

4. 数组与切片

数组(固定长度,少用)

var a [3]int               // [0 0 0]
b := [3]int{1, 2, 3}
c := [...]int{4, 5}        // [2]int

切片(动态长度,常用)

s := []int{1, 2, 3}
s = append(s, 4)            // [1 2 3 4]
sub := s[1:3]               // [2 3]
make([]int, 5)             // [0 0 0 0 0]
make([]int, 0, 5)          // cap=5, len=0

append 可能返回新底层数组,必须接收返回值:

s = append(s, 5)

遍历

for i, v := range s {
    fmt.Println(i, v)
}

5. map

m := map[string]int{
    "Alice": 90,
    "Bob":   80,
}

m["Carol"] = 85
delete(m, "Bob")

// 检查 key 是否存在
score, ok := m["Alice"]
if ok {
    fmt.Println(score)
}

for k, v := range m {
    fmt.Println(k, v)
}

map 遍历顺序不固定。并发读写需要加锁(sync.Mutex 或 sync.Map)。

6. struct 结构体

type Person struct {
    Name string
    Age  int
}

p := Person{Name: "Alice", Age: 30}
fmt.Println(p.Name)

// 指针访问字段,语法糖自动解引用
pp := &p
pp.Age = 31
fmt.Println(p.Age) // 31

匿名字段(嵌套)

type Employee struct {
    Person // 匿名字段,相当于 Name/Age 被提升
    Title  string
}

e := Employee{Person: Person{Name: "Bob"}, Title: "Eng"}
fmt.Println(e.Name) // Bob

结构体标签(Tag)

type User struct {
    Name string `json:"name" validate:"required"`
}

可被 encoding/json、reflect 读取。

7. 字面量构造

切片、map、结构体字面量都支持行内初始化:

users := []User{
    {Name: "A"},
    {Name: "B"},
}

小结

掌握基本类型、指针、切片、map、struct 后,你已经可以建模任意业务数据。下一章学习方法与接口。