第三章:复合数据结构——Go的集合类型

在PHP中,数组(array)是一个万能的数据结构,既可以做索引数组,也可以做关联数组(哈希表)。Go则将这些功能拆分成了更专门、更高效的类型:数组、切片和Map。

3.1 数组 (Array) #

Go的数组是定长的,一旦定义了长度,就不能改变。这使得它在实际开发中不那么常用,但它是理解切片的基础。

func main() {
    // 声明一个长度为3的整数数组,所有元素初始化为0
    var a [3]int
    fmt.Println(a) // [0 0 0]

    // 声明并初始化
    b := [3]int{10, 20, 30}
    fmt.Println(b) // [10 20 30]

    // 让编译器自动计算长度
    c := [...]int{1, 2, 3, 4, 5}
    fmt.Println(len(c)) // 5

    // 数组是值类型,赋值或传参时会完整拷贝一份
    d := b
    d[0] = 99
    fmt.Println(b) // [10 20 30] (b没有被改变)
    fmt.Println(d) // [99 20 30]
}

3.2 切片 (Slice) #

切片是Go中最常用、最强大的集合类型,它动态可变,可以看作是PHP中索引数组的替代品。切片是对底层数组的一个“视图”或“引用”。

func main() {
    // PHP: $arr = ['a', 'b', 'c'];
    // Go:
    s := []string{"a", "b", "c"}

    // 使用make创建切片,指定长度和容量
    // 创建一个长度为3,容量为5的切片
    s2 := make([]string, 3, 5)

    // 添加元素 (append会返回一个新的切片)
    s = append(s, "d", "e")
    fmt.Println(s) // [a b c d e]
    fmt.Println("Length:", len(s)) // 长度: 5
    fmt.Println("Capacity:", cap(s)) // 容量: (可能大于5,Go会自动扩容)

    // 切片操作 (类似PHP的array_slice)
    // s[low:high] -> 从索引low到high-1
    sub := s[1:3] // 包含s[1]和s[2]
    fmt.Println(sub) // [b c]

    // 切片是引用类型
    // 修改切片sub会影响到底层数组,从而影响原始切片s
    sub[0] = "X"
    fmt.Println(s) // [a X c d e] (s也被改变了)
}

3.3 Map #

Map是键值对的集合,等同于PHP中的关联数组。

func main() {
    // PHP: $user = ['name' => 'John Doe', 'age' => 30];
    // Go:
    // 使用make创建map
    user := make(map[string]interface{}) // `interface{}`是空接口,可以代表任何类型,类似PHP的混合类型
    user["name"] = "John Doe"
    user["age"] = 30

    // 声明并初始化
    scores := map[string]int{
        "alice": 95,
        "bob":   80,
    }
    fmt.Println(scores) // map[alice:95 bob:80]

    // 读取值
    fmt.Println(scores["alice"]) // 95

    // 读取一个不存在的键,会返回该值类型的零值
    fmt.Println(scores["charlie"]) // 0 (int的零值)

    // 如何判断键是否存在?使用“comma ok”语法
    score, ok := scores["charlie"]
    if ok {
        fmt.Println("Charlie's score:", score)
    } else {
        fmt.Println("Charlie is not in the map.")
    }

    // 删除键
    delete(scores, "bob")
    fmt.Println(scores) // map[alice:95]
}

3.4 结构体 (Struct) #

结构体是自定义的、将不同类型的字段聚合在一起形成的数据类型。它非常像PHP中的一个没有方法class,或者一个有固定键和类型的关联数组。

// 定义一个User结构体
type User struct {
    ID        int
    FirstName string
    LastName  string
    IsActive  bool
}

func main() {
    // 创建结构体实例
    var u1 User
    u1.ID = 1
    u1.FirstName = "John"
    u1.LastName = "Doe"
    u1.IsActive = true

    // 使用字面量创建
    u2 := User{
        ID:        2,
        FirstName: "Jane",
        LastName:  "Doe",
        IsActive:  false,
    }

    // 也可以按顺序,但不推荐
    u3 := User{3, "Alice", "Wonder", true}

    fmt.Println(u1) // {1 John Doe true}
    fmt.Println(u2.FirstName) // Jane
    fmt.Println(u3)
}

Struct是构建复杂数据模型的基础,在后续的Web开发和API设计中至关重要。