# 数据结构

数组

数组基础

数组声明和初始化

package main

import "fmt"

func main() {
    // 数组声明的几种方式
    var arr1 [5]int  // 声明长度为5的整数数组,零值初始化
    fmt.Printf("零值数组: %v\n", arr1)
    
    // 声明并初始化
    var arr2 = [5]int{1, 2, 3, 4, 5}
    fmt.Printf("初始化数组: %v\n", arr2)
    
    // 简短声明
    arr3 := [3]string{"Go", "Python", "Java"}
    fmt.Printf("字符串数组: %v\n", arr3)
    
    // 让编译器推断长度
    arr4 := [...]int{10, 20, 30, 40}
    fmt.Printf("推断长度数组: %v,长度: %d\n", arr4, len(arr4))
    
    // 指定索引初始化
    arr5 := [5]int{1: 100, 3: 300}
    fmt.Printf("指定索引初始化: %v\n", arr5)
    
    // 数组的长度是类型的一部分
    fmt.Printf("arr2的类型: %T\n", arr2)
    fmt.Printf("arr3的类型: %T\n", arr3)
}
go run array_basic.go

数组操作

package main

import "fmt"

func main() {
    // 创建数组
    numbers := [5]int{10, 20, 30, 40, 50}
    
    // 访问和修改元素
    fmt.Printf("原数组: %v\n", numbers)
    fmt.Printf("第一个元素: %d\n", numbers[0])
    fmt.Printf("最后一个元素: %d\n", numbers[len(numbers)-1])
    
    // 修改元素
    numbers[2] = 999
    fmt.Printf("修改后: %v\n", numbers)
    
    // 遍历数组
    fmt.Println("\n使用索引遍历:")
    for i := 0; i < len(numbers); i++ {
        fmt.Printf("索引 %d: 值 %d\n", i, numbers[i])
    }
    
    fmt.Println("\n使用range遍历:")
    for index, value := range numbers {
        fmt.Printf("索引 %d: 值 %d\n", index, value)
    }
    
    // 数组比较
    arr1 := [3]int{1, 2, 3}
    arr2 := [3]int{1, 2, 3}
    arr3 := [3]int{1, 2, 4}
    
    fmt.Printf("\narr1 == arr2: %t\n", arr1 == arr2)
    fmt.Printf("arr1 == arr3: %t\n", arr1 == arr3)
    
    // 数组复制
    original := [3]int{1, 2, 3}
    copy := original  // 值复制
    copy[0] = 999
    
    fmt.Printf("\n原数组: %v\n", original)
    fmt.Printf("复制数组: %v\n", copy)
}
go run array_operations.go

多维数组

package main

import "fmt"

func main() {
    // 二维数组
    var matrix [3][4]int
    
    // 初始化二维数组
    matrix = [3][4]int{
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12},
    }
    
    fmt.Println("二维数组:")
    for i := 0; i < len(matrix); i++ {
        for j := 0; j < len(matrix[i]); j++ {
            fmt.Printf("%3d ", matrix[i][j])
        }
        fmt.Println()
    }
    
    // 使用range遍历二维数组
    fmt.Println("\n使用range遍历:")
    for i, row := range matrix {
        fmt.Printf("第%d行: ", i+1)
        for j, val := range row {
            fmt.Printf("[%d,%d]=%d ", i, j, val)
        }
        fmt.Println()
    }
    
    // 三维数组示例
    cube := [2][2][2]int{
        {
            {1, 2},
            {3, 4},
        },
        {
            {5, 6},
            {7, 8},
        },
    }
    
    fmt.Println("\n三维数组:")
    for i, plane := range cube {
        fmt.Printf("平面 %d:\n", i)
        for j, row := range plane {
            fmt.Printf("  行 %d: %v\n", j, row)
        }
    }
}
go run array_multidimensional.go

切片

切片基础

切片声明和创建

package main

import "fmt"

func main() {
    // 切片声明
    var slice1 []int
    fmt.Printf("空切片: %v, 长度: %d, 容量: %d\n", slice1, len(slice1), cap(slice1))
    fmt.Printf("是否为nil: %t\n", slice1 == nil)
    
    // 使用make创建切片
    slice2 := make([]int, 5)  // 长度为5,容量为5
    fmt.Printf("make切片: %v, 长度: %d, 容量: %d\n", slice2, len(slice2), cap(slice2))
    
    slice3 := make([]int, 3, 10)  // 长度为3,容量为10
    fmt.Printf("指定容量: %v, 长度: %d, 容量: %d\n", slice3, len(slice3), cap(slice3))
    
    // 切片字面量
    slice4 := []int{1, 2, 3, 4, 5}
    fmt.Printf("字面量切片: %v, 长度: %d, 容量: %d\n", slice4, len(slice4), cap(slice4))
    
    // 从数组创建切片
    arr := [5]int{10, 20, 30, 40, 50}
    slice5 := arr[1:4]  // 从索引1到3(不包括4)
    fmt.Printf("数组切片: %v, 长度: %d, 容量: %d\n", slice5, len(slice5), cap(slice5))
    
    // 切片的切片
    slice6 := slice4[1:3]
    fmt.Printf("切片的切片: %v, 长度: %d, 容量: %d\n", slice6, len(slice6), cap(slice6))
}
go run slice_basic.go

切片操作

package main

import "fmt"

func main() {
    // 创建切片
    slice := []int{1, 2, 3, 4, 5}
    fmt.Printf("原切片: %v\n", slice)
    
    // append操作
    slice = append(slice, 6)
    fmt.Printf("添加一个元素: %v\n", slice)
    
    slice = append(slice, 7, 8, 9)
    fmt.Printf("添加多个元素: %v\n", slice)
    
    // 添加另一个切片
    other := []int{10, 11, 12}
    slice = append(slice, other...)
    fmt.Printf("添加切片: %v\n", slice)
    
    // 切片截取
    fmt.Printf("\n切片截取操作:\n")
    fmt.Printf("slice[2:5]: %v\n", slice[2:5])
    fmt.Printf("slice[:3]: %v\n", slice[:3])
    fmt.Printf("slice[3:]: %v\n", slice[3:])
    fmt.Printf("slice[:]: %v\n", slice[:])
    
    // copy操作
    source := []int{1, 2, 3, 4, 5}
    dest := make([]int, 3)
    
    n := copy(dest, source)
    fmt.Printf("\n复制操作:\n")
    fmt.Printf("源切片: %v\n", source)
    fmt.Printf("目标切片: %v\n", dest)
    fmt.Printf("复制了 %d 个元素\n", n)
    
    // 删除元素(通过切片重组)
    numbers := []int{1, 2, 3, 4, 5, 6, 7}
    fmt.Printf("\n删除操作:\n")
    fmt.Printf("原切片: %v\n", numbers)
    
    // 删除索引2的元素
    index := 2
    numbers = append(numbers[:index], numbers[index+1:]...)
    fmt.Printf("删除索引2后: %v\n", numbers)
}
go run slice_operations.go

切片的内存管理

package main

import "fmt"

func main() {
    // 切片的底层数组
    arr := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    slice1 := arr[2:5]
    slice2 := arr[3:6]
    
    fmt.Printf("原数组: %v\n", arr)
    fmt.Printf("slice1: %v\n", slice1)
    fmt.Printf("slice2: %v\n", slice2)
    
    // 修改slice1会影响底层数组和slice2
    slice1[1] = 999
    fmt.Printf("\n修改slice1[1]后:\n")
    fmt.Printf("数组: %v\n", arr)
    fmt.Printf("slice1: %v\n", slice1)
    fmt.Printf("slice2: %v\n", slice2)
    
    // 切片扩容
    fmt.Printf("\n切片扩容示例:\n")
    slice := make([]int, 0, 2)
    fmt.Printf("初始: len=%d, cap=%d, %v\n", len(slice), cap(slice), slice)
    
    for i := 0; i < 10; i++ {
        slice = append(slice, i)
        fmt.Printf("添加%d: len=%d, cap=%d, %v\n", i, len(slice), cap(slice), slice)
    }
    
    // 演示切片的引用特性
    fmt.Printf("\n切片引用特性:\n")
    original := []int{1, 2, 3, 4, 5}
    reference := original
    
    fmt.Printf("原切片: %v\n", original)
    fmt.Printf("引用切片: %v\n", reference)
    
    reference[0] = 999
    fmt.Printf("修改引用后:\n")
    fmt.Printf("原切片: %v\n", original)
    fmt.Printf("引用切片: %v\n", reference)
    
    // 创建独立副本
    independent := make([]int, len(original))
    copy(independent, original)
    independent[1] = 888
    
    fmt.Printf("\n独立副本:\n")
    fmt.Printf("原切片: %v\n", original)
    fmt.Printf("独立副本: %v\n", independent)
}
go run slice_memory.go

切片的高级应用

切片作为函数参数

package main

import "fmt"

// 修改切片元素
func modifySlice(s []int) {
    if len(s) > 0 {
        s[0] = 999
    }
    fmt.Printf("函数内切片: %v\n", s)
}

// 向切片添加元素(错误方式)
func appendWrong(s []int, value int) {
    s = append(s, value)
    fmt.Printf("函数内添加后: %v\n", s)
}

// 向切片添加元素(正确方式)
func appendCorrect(s []int, value int) []int {
    s = append(s, value)
    fmt.Printf("函数内添加后: %v\n", s)
    return s
}

// 使用指针修改切片
func appendWithPointer(s *[]int, value int) {
    *s = append(*s, value)
    fmt.Printf("函数内添加后: %v\n", *s)
}

// 过滤切片
func filter(s []int, predicate func(int) bool) []int {
    var result []int
    for _, v := range s {
        if predicate(v) {
            result = append(result, v)
        }
    }
    return result
}

// 映射切片
func mapSlice(s []int, fn func(int) int) []int {
    result := make([]int, len(s))
    for i, v := range s {
        result[i] = fn(v)
    }
    return result
}

func main() {
    // 修改切片元素
    slice1 := []int{1, 2, 3, 4, 5}
    fmt.Printf("调用前: %v\n", slice1)
    modifySlice(slice1)
    fmt.Printf("调用后: %v\n", slice1)
    
    // 错误的添加方式
    fmt.Printf("\n错误的添加方式:\n")
    slice2 := []int{1, 2, 3}
    fmt.Printf("调用前: %v\n", slice2)
    appendWrong(slice2, 4)
    fmt.Printf("调用后: %v\n", slice2)  // 没有变化
    
    // 正确的添加方式
    fmt.Printf("\n正确的添加方式:\n")
    slice3 := []int{1, 2, 3}
    fmt.Printf("调用前: %v\n", slice3)
    slice3 = appendCorrect(slice3, 4)
    fmt.Printf("调用后: %v\n", slice3)
    
    // 使用指针
    fmt.Printf("\n使用指针:\n")
    slice4 := []int{1, 2, 3}
    fmt.Printf("调用前: %v\n", slice4)
    appendWithPointer(&slice4, 4)
    fmt.Printf("调用后: %v\n", slice4)
    
    // 函数式操作
    numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    
    // 过滤偶数
    evens := filter(numbers, func(n int) bool { return n%2 == 0 })
    fmt.Printf("\n偶数: %v\n", evens)
    
    // 映射为平方
    squares := mapSlice(numbers, func(n int) int { return n * n })
    fmt.Printf("平方: %v\n", squares)
}
go run slice_functions.go

映射(Map)

映射基础

映射的创建和初始化

package main

import "fmt"

func main() {
    // 声明映射
    var map1 map[string]int
    fmt.Printf("空映射: %v\n", map1)
    fmt.Printf("是否为nil: %t\n", map1 == nil)
    
    // 使用make创建映射
    map2 := make(map[string]int)
    fmt.Printf("make映射: %v\n", map2)
    fmt.Printf("是否为nil: %t\n", map2 == nil)
    
    // 映射字面量
    map3 := map[string]int{
        "apple":  5,
        "banana": 3,
        "orange": 8,
    }
    fmt.Printf("字面量映射: %v\n", map3)
    
    // 空映射字面量
    map4 := map[string]int{}
    fmt.Printf("空字面量映射: %v\n", map4)
    
    // 不同类型的映射
    ages := map[string]int{
        "Alice":   25,
        "Bob":     30,
        "Charlie": 35,
    }
    
    scores := map[string]float64{
        "Math":    95.5,
        "English": 87.0,
        "Science": 92.3,
    }
    
    fmt.Printf("年龄映射: %v\n", ages)
    fmt.Printf("分数映射: %v\n", scores)
    
    // 复杂类型的映射
    students := map[int]map[string]interface{}{
        1: {
            "name": "Alice",
            "age":  20,
            "gpa":  3.8,
        },
        2: {
            "name": "Bob",
            "age":  22,
            "gpa":  3.6,
        },
    }
    
    fmt.Printf("学生映射: %v\n", students)
}
go run map_basic.go

映射操作

package main

import "fmt"

func main() {
    // 创建映射
    fruits := map[string]int{
        "apple":  5,
        "banana": 3,
        "orange": 8,
    }
    
    fmt.Printf("原映射: %v\n", fruits)
    
    // 访问元素
    fmt.Printf("苹果数量: %d\n", fruits["apple"])
    fmt.Printf("不存在的键: %d\n", fruits["grape"])  // 返回零值
    
    // 检查键是否存在
    value, exists := fruits["banana"]
    fmt.Printf("香蕉存在: %t, 数量: %d\n", exists, value)
    
    value, exists = fruits["grape"]
    fmt.Printf("葡萄存在: %t, 数量: %d\n", exists, value)
    
    // 添加和修改元素
    fruits["grape"] = 12  // 添加新键
    fruits["apple"] = 10  // 修改现有键
    fmt.Printf("添加和修改后: %v\n", fruits)
    
    // 删除元素
    delete(fruits, "banana")
    fmt.Printf("删除香蕉后: %v\n", fruits)
    
    // 删除不存在的键(安全操作)
    delete(fruits, "watermelon")
    fmt.Printf("删除不存在键后: %v\n", fruits)
    
    // 获取映射长度
    fmt.Printf("映射长度: %d\n", len(fruits))
    
    // 遍历映射
    fmt.Println("\n遍历映射:")
    for key, value := range fruits {
        fmt.Printf("%s: %d\n", key, value)
    }
    
    // 只遍历键
    fmt.Println("\n只遍历键:")
    for key := range fruits {
        fmt.Printf("键: %s\n", key)
    }
    
    // 只遍历值
    fmt.Println("\n只遍历值:")
    for _, value := range fruits {
        fmt.Printf("值: %d\n", value)
    }
}
go run map_operations.go

映射的高级应用

package main

import (
    "fmt"
    "sort"
)

func main() {
    // 统计字符出现次数
    text := "hello world"
    charCount := make(map[rune]int)
    
    for _, char := range text {
        charCount[char]++
    }
    
    fmt.Printf("字符统计: %v\n", charCount)
    
    // 分组操作
    students := []struct {
        Name  string
        Grade string
        Score int
    }{
        {"Alice", "A", 95},
        {"Bob", "B", 87},
        {"Charlie", "A", 92},
        {"David", "B", 78},
        {"Eve", "A", 88},
    }
    
    // 按年级分组
    gradeGroups := make(map[string][]string)
    for _, student := range students {
        gradeGroups[student.Grade] = append(gradeGroups[student.Grade], student.Name)
    }
    
    fmt.Printf("\n按年级分组: %v\n", gradeGroups)
    
    // 计算平均分
    gradeAverage := make(map[string]float64)
    gradeCount := make(map[string]int)
    gradeSum := make(map[string]int)
    
    for _, student := range students {
        gradeSum[student.Grade] += student.Score
        gradeCount[student.Grade]++
    }
    
    for grade := range gradeSum {
        gradeAverage[grade] = float64(gradeSum[grade]) / float64(gradeCount[grade])
    }
    
    fmt.Printf("年级平均分: %v\n", gradeAverage)
    
    // 映射排序(按键排序)
    scores := map[string]int{
        "Alice":   95,
        "Bob":     87,
        "Charlie": 92,
        "David":   78,
        "Eve":     88,
    }
    
    // 提取键并排序
    var names []string
    for name := range scores {
        names = append(names, name)
    }
    sort.Strings(names)
    
    fmt.Printf("\n按姓名排序:\n")
    for _, name := range names {
        fmt.Printf("%s: %d\n", name, scores[name])
    }
    
    // 按值排序
    type kv struct {
        Key   string
        Value int
    }
    
    var sortedScores []kv
    for k, v := range scores {
        sortedScores = append(sortedScores, kv{k, v})
    }
    
    sort.Slice(sortedScores, func(i, j int) bool {
        return sortedScores[i].Value > sortedScores[j].Value
    })
    
    fmt.Printf("\n按分数排序:\n")
    for _, kv := range sortedScores {
        fmt.Printf("%s: %d\n", kv.Key, kv.Value)
    }
}
go run map_advanced.go

结构体

结构体基础

结构体定义和初始化

package main

import "fmt"

// 定义结构体
type Person struct {
    Name string
    Age  int
    City string
}

// 嵌套结构体
type Address struct {
    Street  string
    City    string
    ZipCode string
}

type Employee struct {
    ID      int
    Name    string
    Address Address
    Salary  float64
}

// 匿名字段
type Student struct {
    string  // 匿名字段
    int     // 匿名字段
    Grade   string
}

func main() {
    // 结构体初始化的几种方式
    
    // 1. 零值初始化
    var p1 Person
    fmt.Printf("零值结构体: %+v\n", p1)
    
    // 2. 字段赋值
    p1.Name = "Alice"
    p1.Age = 25
    p1.City = "New York"
    fmt.Printf("赋值后: %+v\n", p1)
    
    // 3. 结构体字面量(按顺序)
    p2 := Person{"Bob", 30, "Los Angeles"}
    fmt.Printf("按顺序初始化: %+v\n", p2)
    
    // 4. 结构体字面量(指定字段)
    p3 := Person{
        Name: "Charlie",
        Age:  35,
        City: "Chicago",
    }
    fmt.Printf("指定字段初始化: %+v\n", p3)
    
    // 5. 部分字段初始化
    p4 := Person{
        Name: "David",
        Age:  28,
        // City字段使用零值
    }
    fmt.Printf("部分初始化: %+v\n", p4)
    
    // 嵌套结构体
    emp := Employee{
        ID:   1001,
        Name: "John Doe",
        Address: Address{
            Street:  "123 Main St",
            City:    "Boston",
            ZipCode: "02101",
        },
        Salary: 75000.0,
    }
    fmt.Printf("\n嵌套结构体: %+v\n", emp)
    
    // 匿名字段
    s := Student{
        string: "Jane Smith",  // 匿名string字段
        int:    20,           // 匿名int字段
        Grade:  "A",
    }
    fmt.Printf("\n匿名字段结构体: %+v\n", s)
    fmt.Printf("访问匿名字段: 姓名=%s, 年龄=%d\n", s.string, s.int)
}
go run struct_basic.go

结构体方法

package main

import (
    "fmt"
    "math"
)

// 定义结构体
type Rectangle struct {
    Width  float64
    Height float64
}

type Circle struct {
    Radius float64
}

// 值接收者方法
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func (r Rectangle) Perimeter() float64 {
    return 2 * (r.Width + r.Height)
}

// 指针接收者方法
func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}

func (r *Rectangle) SetDimensions(width, height float64) {
    r.Width = width
    r.Height = height
}

// Circle的方法
func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

func (c Circle) Circumference() float64 {
    return 2 * math.Pi * c.Radius
}

func (c *Circle) SetRadius(radius float64) {
    c.Radius = radius
}

// 字符串表示方法
func (r Rectangle) String() string {
    return fmt.Sprintf("Rectangle{Width: %.2f, Height: %.2f}", r.Width, r.Height)
}

func (c Circle) String() string {
    return fmt.Sprintf("Circle{Radius: %.2f}", c.Radius)
}

func main() {
    // 创建矩形
    rect := Rectangle{Width: 10, Height: 5}
    fmt.Printf("矩形: %s\n", rect)
    fmt.Printf("面积: %.2f\n", rect.Area())
    fmt.Printf("周长: %.2f\n", rect.Perimeter())
    
    // 使用指针接收者方法
    fmt.Printf("\n缩放前: %s\n", rect)
    rect.Scale(2.0)
    fmt.Printf("缩放后: %s\n", rect)
    
    // 修改尺寸
    rect.SetDimensions(8, 6)
    fmt.Printf("修改尺寸后: %s\n", rect)
    
    // 创建圆形
    circle := Circle{Radius: 3}
    fmt.Printf("\n圆形: %s\n", circle)
    fmt.Printf("面积: %.2f\n", circle.Area())
    fmt.Printf("周长: %.2f\n", circle.Circumference())
    
    // 修改半径
    circle.SetRadius(5)
    fmt.Printf("修改半径后: %s\n", circle)
    fmt.Printf("新面积: %.2f\n", circle.Area())
    
    // 演示值接收者vs指针接收者
    fmt.Printf("\n值接收者vs指针接收者:\n")
    
    rect2 := Rectangle{Width: 4, Height: 3}
    fmt.Printf("原始矩形: %s\n", rect2)
    
    // 值接收者不会修改原始值
    area := rect2.Area()  // 值接收者
    fmt.Printf("计算面积后: %s (面积: %.2f)\n", rect2, area)
    
    // 指针接收者会修改原始值
    rect2.Scale(1.5)  // 指针接收者
    fmt.Printf("缩放后: %s\n", rect2)
}
go run struct_methods.go

结构体嵌入和组合

package main

import "fmt"

// 基础结构体
type Animal struct {
    Name string
    Age  int
}

func (a Animal) Speak() string {
    return fmt.Sprintf("%s makes a sound", a.Name)
}

func (a Animal) Info() string {
    return fmt.Sprintf("%s is %d years old", a.Name, a.Age)
}

// 嵌入Animal的结构体
type Dog struct {
    Animal  // 嵌入
    Breed string
}

// Dog特有的方法
func (d Dog) Bark() string {
    return fmt.Sprintf("%s barks: Woof!", d.Name)
}

// 重写嵌入类型的方法
func (d Dog) Speak() string {
    return fmt.Sprintf("%s barks", d.Name)
}

type Cat struct {
    Animal
    IndoorOnly bool
}

func (c Cat) Meow() string {
    return fmt.Sprintf("%s meows: Meow!", c.Name)
}

func (c Cat) Speak() string {
    return fmt.Sprintf("%s meows", c.Name)
}

// 多重嵌入
type Engine struct {
    Power int
    Type  string
}

func (e Engine) Start() string {
    return fmt.Sprintf("Engine started: %d HP %s", e.Power, e.Type)
}

type GPS struct {
    Brand string
}

func (g GPS) Navigate() string {
    return fmt.Sprintf("Navigating with %s GPS", g.Brand)
}

type Car struct {
    Engine
    GPS
    Brand string
    Model string
}

func (c Car) Drive() string {
    return fmt.Sprintf("Driving %s %s", c.Brand, c.Model)
}

func main() {
    // 创建Dog实例
    dog := Dog{
        Animal: Animal{
            Name: "Buddy",
            Age:  3,
        },
        Breed: "Golden Retriever",
    }
    
    fmt.Printf("狗的信息: %+v\n", dog)
    fmt.Printf("基本信息: %s\n", dog.Info())    // 继承的方法
    fmt.Printf("叫声: %s\n", dog.Speak())       // 重写的方法
    fmt.Printf("吠叫: %s\n", dog.Bark())        // 特有方法
    fmt.Printf("直接访问名字: %s\n", dog.Name)    // 直接访问嵌入字段
    
    // 创建Cat实例
    cat := Cat{
        Animal: Animal{
            Name: "Whiskers",
            Age:  2,
        },
        IndoorOnly: true,
    }
    
    fmt.Printf("\n猫的信息: %+v\n", cat)
    fmt.Printf("基本信息: %s\n", cat.Info())
    fmt.Printf("叫声: %s\n", cat.Speak())
    fmt.Printf("喵叫: %s\n", cat.Meow())
    
    // 多重嵌入示例
    car := Car{
        Engine: Engine{
            Power: 300,
            Type:  "V6",
        },
        GPS: GPS{
            Brand: "Garmin",
        },
        Brand: "Toyota",
        Model: "Camry",
    }
    
    fmt.Printf("\n汽车信息: %+v\n", car)
    fmt.Printf("启动引擎: %s\n", car.Start())      // Engine的方法
    fmt.Printf("导航: %s\n", car.Navigate())      // GPS的方法
    fmt.Printf("驾驶: %s\n", car.Drive())        // Car的方法
    
    // 访问嵌入字段
    fmt.Printf("引擎功率: %d HP\n", car.Power)     // 直接访问Engine.Power
    fmt.Printf("GPS品牌: %s\n", car.GPS.Brand)   // 通过类型名访问
    
    // 类型断言和接口
    animals := []Animal{dog.Animal, cat.Animal}
    fmt.Printf("\n动物列表:\n")
    for i, animal := range animals {
        fmt.Printf("%d. %s\n", i+1, animal.Speak())
    }
}
go run struct_embedding.go

结构体标签和反射

结构体标签

package main

import (
    "encoding/json"
    "fmt"
    "reflect"
)

// 带标签的结构体
type User struct {
    ID       int    `json:"id" db:"user_id" validate:"required"`
    Name     string `json:"name" db:"full_name" validate:"required,min=2"`
    Email    string `json:"email" db:"email_address" validate:"required,email"`
    Age      int    `json:"age" db:"age" validate:"min=0,max=120"`
    Password string `json:"-" db:"password_hash"`  // json:"-" 表示不序列化
    IsActive bool   `json:"is_active" db:"active"`
}

// 自定义标签
type Product struct {
    Name        string  `form:"name" binding:"required"`
    Price       float64 `form:"price" binding:"required,gt=0"`
    Description string  `form:"description"`
    Category    string  `form:"category" binding:"required"`
}

// 读取结构体标签
func printStructTags(v interface{}) {
    t := reflect.TypeOf(v)
    if t.Kind() == reflect.Ptr {
        t = t.Elem()
    }
    
    fmt.Printf("结构体 %s 的标签信息:\n", t.Name())
    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        fmt.Printf("字段: %s\n", field.Name)
        
        if jsonTag := field.Tag.Get("json"); jsonTag != "" {
            fmt.Printf("  json: %s\n", jsonTag)
        }
        if dbTag := field.Tag.Get("db"); dbTag != "" {
            fmt.Printf("  db: %s\n", dbTag)
        }
        if validateTag := field.Tag.Get("validate"); validateTag != "" {
            fmt.Printf("  validate: %s\n", validateTag)
        }
        fmt.Println()
    }
}

func main() {
    // 创建用户实例
    user := User{
        ID:       1,
        Name:     "Alice Johnson",
        Email:    "alice@example.com",
        Age:      28,
        Password: "secret123",
        IsActive: true,
    }
    
    // JSON序列化
    jsonData, err := json.MarshalIndent(user, "", "  ")
    if err != nil {
        fmt.Printf("JSON序列化错误: %v\n", err)
        return
    }
    
    fmt.Printf("JSON序列化结果:\n%s\n\n", jsonData)
    
    // JSON反序列化
    jsonStr := `{
        "id": 2,
        "name": "Bob Smith",
        "email": "bob@example.com",
        "age": 32,
        "is_active": false
    }`
    
    var newUser User
    err = json.Unmarshal([]byte(jsonStr), &newUser)
    if err != nil {
        fmt.Printf("JSON反序列化错误: %v\n", err)
        return
    }
    
    fmt.Printf("反序列化结果: %+v\n\n", newUser)
    
    // 打印结构体标签
    printStructTags(user)
    
    // 产品示例
    product := Product{
        Name:        "Laptop",
        Price:       999.99,
        Description: "High-performance laptop",
        Category:    "Electronics",
    }
    
    fmt.Printf("产品信息: %+v\n\n", product)
    printStructTags(product)
}
go run struct_tags.go

接口

接口基础

接口定义和实现

package main

import (
    "fmt"
    "math"
)

// 定义接口
type Shape interface {
    Area() float64
    Perimeter() float64
}

// 另一个接口
type Drawable interface {
    Draw() string
}

// 组合接口
type DrawableShape interface {
    Shape
    Drawable
}

// 实现Shape接口的结构体
type Rectangle struct {
    Width, Height float64
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func (r Rectangle) Perimeter() float64 {
    return 2 * (r.Width + r.Height)
}

func (r Rectangle) Draw() string {
    return fmt.Sprintf("Drawing a rectangle %.1fx%.1f", r.Width, r.Height)
}

type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
    return 2 * math.Pi * c.Radius
}

func (c Circle) Draw() string {
    return fmt.Sprintf("Drawing a circle with radius %.1f", c.Radius)
}

type Triangle struct {
    A, B, C float64
}

func (t Triangle) Area() float64 {
    // 使用海伦公式
    s := (t.A + t.B + t.C) / 2
    return math.Sqrt(s * (s - t.A) * (s - t.B) * (s - t.C))
}

func (t Triangle) Perimeter() float64 {
    return t.A + t.B + t.C
}

func (t Triangle) Draw() string {
    return fmt.Sprintf("Drawing a triangle with sides %.1f, %.1f, %.1f", t.A, t.B, t.C)
}

// 使用接口的函数
func printShapeInfo(s Shape) {
    fmt.Printf("面积: %.2f\n", s.Area())
    fmt.Printf("周长: %.2f\n", s.Perimeter())
}

func drawShape(d Drawable) {
    fmt.Println(d.Draw())
}

func processDrawableShape(ds DrawableShape) {
    fmt.Println(ds.Draw())
    fmt.Printf("面积: %.2f, 周长: %.2f\n", ds.Area(), ds.Perimeter())
}

func main() {
    // 创建不同的形状
    rect := Rectangle{Width: 10, Height: 5}
    circle := Circle{Radius: 3}
    triangle := Triangle{A: 3, B: 4, C: 5}
    
    // 使用Shape接口
    shapes := []Shape{rect, circle, triangle}
    
    fmt.Println("所有形状的信息:")
    for i, shape := range shapes {
        fmt.Printf("\n形状 %d:\n", i+1)
        printShapeInfo(shape)
    }
    
    // 使用Drawable接口
    fmt.Println("\n绘制所有形状:")
    drawables := []Drawable{rect, circle, triangle}
    for _, drawable := range drawables {
        drawShape(drawable)
    }
    
    // 使用组合接口
    fmt.Println("\n使用组合接口:")
    drawableShapes := []DrawableShape{rect, circle, triangle}
    for i, ds := range drawableShapes {
        fmt.Printf("\n形状 %d:\n", i+1)
        processDrawableShape(ds)
    }
    
    // 接口类型断言
    fmt.Println("\n类型断言示例:")
    var s Shape = rect
    
    if r, ok := s.(Rectangle); ok {
        fmt.Printf("这是一个矩形,宽度: %.1f, 高度: %.1f\n", r.Width, r.Height)
    }
    
    // switch类型断言
    fmt.Println("\nswitch类型断言:")
    for _, shape := range shapes {
        switch v := shape.(type) {
        case Rectangle:
            fmt.Printf("矩形: %.1f x %.1f\n", v.Width, v.Height)
        case Circle:
            fmt.Printf("圆形: 半径 %.1f\n", v.Radius)
        case Triangle:
            fmt.Printf("三角形: 边长 %.1f, %.1f, %.1f\n", v.A, v.B, v.C)
        default:
            fmt.Printf("未知形状: %T\n", v)
        }
    }
}
go run interface_basic.go

空接口和类型断言

package main

import "fmt"

// 空接口可以存储任何类型的值
func describe(i interface{}) {
    fmt.Printf("值: %v, 类型: %T\n", i, i)
}

// 类型断言函数
func processValue(value interface{}) {
    switch v := value.(type) {
    case int:
        fmt.Printf("整数: %d, 平方: %d\n", v, v*v)
    case string:
        fmt.Printf("字符串: %s, 长度: %d\n", v, len(v))
    case bool:
        fmt.Printf("布尔值: %t\n", v)
    case []int:
        fmt.Printf("整数切片: %v, 长度: %d\n", v, len(v))
    case map[string]int:
        fmt.Printf("字符串到整数的映射: %v\n", v)
    case nil:
        fmt.Println("nil值")
    default:
        fmt.Printf("未知类型: %T, 值: %v\n", v, v)
    }
}

// 安全的类型断言
func safeTypeAssertion(value interface{}) {
    // 检查是否为字符串
    if str, ok := value.(string); ok {
        fmt.Printf("安全断言成功 - 字符串: %s\n", str)
    } else {
        fmt.Printf("不是字符串类型,实际类型: %T\n", value)
    }
    
    // 检查是否为整数
    if num, ok := value.(int); ok {
        fmt.Printf("安全断言成功 - 整数: %d\n", num)
    } else {
        fmt.Printf("不是整数类型,实际类型: %T\n", value)
    }
}

// 通用打印函数
func printAll(values ...interface{}) {
    fmt.Println("打印所有值:")
    for i, value := range values {
        fmt.Printf("  [%d] ", i)
        describe(value)
    }
}

// 通用比较函数
func compare(a, b interface{}) bool {
    return a == b
}

func main() {
    // 空接口示例
    var empty interface{}
    
    fmt.Println("空接口示例:")
    describe(empty)  // nil
    
    empty = 42
    describe(empty)
    
    empty = "Hello, World!"
    describe(empty)
    
    empty = []int{1, 2, 3, 4, 5}
    describe(empty)
    
    empty = map[string]int{"apple": 5, "banana": 3}
    describe(empty)
    
    // 类型断言示例
    fmt.Println("\n类型断言示例:")
    values := []interface{}{
        42,
        "Hello",
        true,
        []int{1, 2, 3},
        map[string]int{"key": 100},
        nil,
        3.14,
        struct{ Name string }{"Test"},
    }
    
    for i, value := range values {
        fmt.Printf("\n值 %d: ", i+1)
        processValue(value)
    }
    
    // 安全类型断言
    fmt.Println("\n安全类型断言:")
    testValues := []interface{}{"hello", 123, 3.14}
    
    for _, value := range testValues {
        fmt.Printf("\n测试值: %v\n", value)
        safeTypeAssertion(value)
    }
    
    // 通用函数示例
    fmt.Println("\n通用函数示例:")
    printAll(1, "hello", true, []int{1, 2}, map[string]int{"a": 1})
    
    // 比较示例
    fmt.Println("\n比较示例:")
    fmt.Printf("42 == 42: %t\n", compare(42, 42))
    fmt.Printf("42 == \"42\": %t\n", compare(42, "42"))
    fmt.Printf("\"hello\" == \"hello\": %t\n", compare("hello", "hello"))
    
    // 接口切片
    fmt.Println("\n接口切片:")
    mixed := []interface{}{1, "two", 3.0, true}
    for i, item := range mixed {
        fmt.Printf("索引 %d: ", i)
        describe(item)
    }
    
    // 接口映射
    fmt.Println("\n接口映射:")
    data := map[string]interface{}{
        "name":    "Alice",
        "age":     30,
        "active":  true,
        "scores":  []int{95, 87, 92},
        "address": map[string]string{"city": "New York", "zip": "10001"},
    }
    
    for key, value := range data {
        fmt.Printf("%s: ", key)
        describe(value)
    }
}
go run interface_empty.go

恭喜!你已经掌握了Go语言的主要数据结构。接下来让我们学习Go语言最强大的特性之一:并发编程,包括goroutine和channel的使用。