Skip to content
<

Golang 数据类型详解

复合数据类型

数组(Array)

数组是固定长度的相同类型元素序列。

go
package main

import "fmt"

func arrayDemo() {
    // 声明数组
    var arr1 [5]int
    arr1[0] = 1
    arr1[1] = 2

    // 初始化数组
    arr2 := [5]int{1, 2, 3, 4, 5}

    // 自动推断长度
    arr3 := [...]int{1, 2, 3, 4, 5, 6}

    // 指定索引初始化
    arr4 := [5]int{0: 10, 2: 20, 4: 40}

    fmt.Println("arr1:", arr1)
    fmt.Println("arr2:", arr2)
    fmt.Println("arr3:", arr3)
    fmt.Println("arr4:", arr4)
    fmt.Println("数组长度:", len(arr2))
}

切片(Slice)

切片是动态数组,是对数组的抽象。

go
func sliceDemo() {
    // 创建切片
    slice1 := []int{1, 2, 3, 4, 5}

    // 使用 make 创建切片
    slice2 := make([]int, 5)      // 长度为5
    slice3 := make([]int, 5, 10)  // 长度5,容量10

    // 切片操作
    slice4 := slice1[1:4]  // [2, 3, 4]
    slice5 := slice1[:3]   // [1, 2, 3]
    slice6 := slice1[2:]   // [3, 4, 5]

    fmt.Println("slice1:", slice1)
    fmt.Println("slice4:", slice4)
    fmt.Printf("长度: %d, 容量: %d\n", len(slice3), cap(slice3))

    // 追加元素
    slice1 = append(slice1, 6, 7, 8)
    fmt.Println("追加后:", slice1)

    // 复制切片
    slice7 := make([]int, len(slice1))
    copy(slice7, slice1)
    fmt.Println("复制的切片:", slice7)
}

映射(Map)

Map 是无序的键值对集合。

go
func mapDemo() {
    // 创建 map
    map1 := make(map[string]int)
    map1["apple"] = 5
    map1["banana"] = 3
    map1["orange"] = 7

    // 字面量初始化
    map2 := map[string]string{
        "name":  "Jackson",
        "city":  "Beijing",
        "job":   "Engineer",
    }

    // 访问元素
    fmt.Println("apple数量:", map1["apple"])

    // 检查键是否存在
    value, exists := map1["grape"]
    if exists {
        fmt.Println("grape数量:", value)
    } else {
        fmt.Println("grape不存在")
    }

    // 删除元素
    delete(map1, "banana")

    // 遍历 map
    fmt.Println("\n遍历 map2:")
    for key, value := range map2 {
        fmt.Printf("%s: %s\n", key, value)
    }

    fmt.Println("map1长度:", len(map1))
}

结构体(Struct)

结构体是字段的集合。

go
// 定义结构体
type Person struct {
    Name    string
    Age     int
    Email   string
    Address string
}

func structDemo() {
    // 创建结构体实例
    person1 := Person{
        Name:    "Jackson",
        Age:     25,
        Email:   "jackson@example.com",
        Address: "Beijing",
    }

    // 简短声明
    person2 := Person{"Alice", 30, "alice@example.com", "Shanghai"}

    // 部分字段初始化
    person3 := Person{Name: "Bob", Age: 28}

    // 访问字段
    fmt.Println("姓名:", person1.Name)
    fmt.Println("年龄:", person1.Age)

    // 修改字段
    person1.Age = 26
    fmt.Println("修改后年龄:", person1.Age)

    // 匿名结构体
    employee := struct {
        Name   string
        Salary float64
    }{
        Name:   "Tom",
        Salary: 50000.0,
    }
    fmt.Printf("员工: %+v\n", employee)

    fmt.Printf("person2: %+v\n", person2)
    fmt.Printf("person3: %+v\n", person3)
}

指针(Pointer)

指针存储变量的内存地址。

go
func pointerDemo() {
    // 基本指针操作
    x := 10
    p := &x  // 获取 x 的地址

    fmt.Println("x的值:", x)
    fmt.Println("x的地址:", p)
    fmt.Println("指针指向的值:", *p)

    // 通过指针修改值
    *p = 20
    fmt.Println("修改后x的值:", x)

    // 结构体指针
    person := &Person{
        Name: "Jackson",
        Age:  25,
    }

    // 可以直接访问字段,Go会自动解引用
    fmt.Println("姓名:", person.Name)
    person.Age = 26
    fmt.Println("年龄:", person.Age)

    // new 函数创建指针
    ptr := new(int)
    *ptr = 100
    fmt.Println("new创建的指针值:", *ptr)
}

接口(Interface)

接口定义对象的行为。

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

// 矩形
type Rectangle struct {
    Width  float64
    Height float64
}

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

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

// 圆形
type Circle struct {
    Radius float64
}

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

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

func interfaceDemo() {
    var s Shape

    // Rectangle 实现了 Shape 接口
    s = Rectangle{Width: 10, Height: 5}
    fmt.Printf("矩形面积: %.2f\n", s.Area())
    fmt.Printf("矩形周长: %.2f\n", s.Perimeter())

    // Circle 也实现了 Shape 接口
    s = Circle{Radius: 7}
    fmt.Printf("圆形面积: %.2f\n", s.Area())
    fmt.Printf("圆形周长: %.2f\n", s.Perimeter())

    // 空接口
    var any interface{}
    any = 42
    fmt.Println("空接口存储int:", any)
    any = "Hello"
    fmt.Println("空接口存储string:", any)
}

类型断言与类型转换

go
func typeAssertionDemo() {
    var i interface{} = "Hello, World"

    // 类型断言
    s, ok := i.(string)
    if ok {
        fmt.Println("字符串值:", s)
    }

    // 类型判断
    switch v := i.(type) {
    case int:
        fmt.Println("整数:", v)
    case string:
        fmt.Println("字符串:", v)
    case bool:
        fmt.Println("布尔:", v)
    default:
        fmt.Println("未知类型")
    }
}

完整示例

go
package main

import "fmt"

type Student struct {
    Name   string
    Age    int
    Scores []int
}

func (s Student) Average() float64 {
    if len(s.Scores) == 0 {
        return 0
    }
    sum := 0
    for _, score := range s.Scores {
        sum += score
    }
    return float64(sum) / float64(len(s.Scores))
}

func main() {
    // 创建学生映射
    students := make(map[string]Student)

    students["001"] = Student{
        Name:   "张三",
        Age:    20,
        Scores: []int{85, 90, 88, 92},
    }

    students["002"] = Student{
        Name:   "李四",
        Age:    21,
        Scores: []int{78, 82, 85, 80},
    }

    // 遍历学生信息
    fmt.Println("=== 学生成绩单 ===")
    for id, student := range students {
        fmt.Printf("\n学号: %s\n", id)
        fmt.Printf("姓名: %s\n", student.Name)
        fmt.Printf("年龄: %d\n", student.Age)
        fmt.Printf("成绩: %v\n", student.Scores)
        fmt.Printf("平均分: %.2f\n", student.Average())
    }
}

运行结果

=== 学生成绩单 ===

学号: 001
姓名: 张三
年龄: 20
成绩: [85 90 88 92]
平均分: 88.75

学号: 002
姓名: 李四
年龄: 21
成绩: [78 82 85 80]
平均分: 81.25

小结

  • 数组:固定长度,类型相同
  • 切片:动态数组,灵活方便
  • Map:键值对集合,无序
  • 结构体:自定义复合类型
  • 指针:存储变量地址,高效传递
  • 接口:定义行为规范,实现多态