Go学习笔记-Data Types

Go语言有丰富的内置数据类型,包括基本类型、复合类型和引用类型。理解这些类型对于编写高效的Go程序至关重要。

基本数据类型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package main

import (
    "fmt"
    "unsafe"
)

func main() {
    // 1. 布尔类型
    var flag bool = true
    var active bool = false
    fmt.Printf("布尔类型: %t, %t\n", flag, active)
    
    // 2. 整数类型
    var int8Var int8 = 127           // -128 到 127
    var int16Var int16 = 32767       // -32768 到 32767
    var int32Var int32 = 2147483647  // -2^31 到 2^31-1
    var int64Var int64 = 9223372036854775807 // -2^63 到 2^63-1
    
    fmt.Printf("int8: %d, int16: %d, int32: %d, int64: %d\n", 
        int8Var, int16Var, int32Var, int64Var)
    
    // 3. 无符号整数类型
    var uint8Var uint8 = 255         // 0 到 255
    var uint16Var uint16 = 65535     // 0 到 65535
    var uint32Var uint32 = 4294967295 // 0 到 2^32-1
    var uint64Var uint64 = 18446744073709551615 // 0 到 2^64-1
    
    fmt.Printf("uint8: %d, uint16: %d, uint32: %d, uint64: %d\n", 
        uint8Var, uint16Var, uint32Var, uint64Var)
    
    // 4. 平台相关的整数类型
    var intVar int = 42        // 32位系统上是int32,64位系统上是int64
    var uintVar uint = 42      // 32位系统上是uint32,64位系统上是uint64
    var uintptrVar uintptr = 0x12345 // 存储指针的整数类型
    
    fmt.Printf("int: %d, uint: %d, uintptr: %x\n", intVar, uintVar, uintptrVar)
    
    // 5. 浮点数类型
    var float32Var float32 = 3.14159
    var float64Var float64 = 3.141592653589793
    
    fmt.Printf("float32: %.5f, float64: %.15f\n", float32Var, float64Var)
    
    // 6. 复数类型
    var complex64Var complex64 = 1 + 2i
    var complex128Var complex128 = 2 + 3i
    
    fmt.Printf("complex64: %v, complex128: %v\n", complex64Var, complex128Var)
}

字符串类型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package main

import "fmt"

func main() {
    // 1. 字符串基础
    var str1 string = "Hello, Go!"
    str2 := "你好,世界!"
    
    fmt.Println("字符串1:", str1)
    fmt.Println("字符串2:", str2)
    
    // 2. 字符串长度
    fmt.Printf("str1长度: %d 字节\n", len(str1))
    fmt.Printf("str2长度: %d 字节\n", len(str2)) // 中文字符占用多个字节
    
    // 3. 字符串是不可变的
    // str1[0] = 'h' // 错误:字符串不可修改
    
    // 4. 字符串拼接
    greeting := str1 + " " + str2
    fmt.Println("拼接结果:", greeting)
    
    // 5. 多行字符串
    multiLine := `这是一个
多行字符串
可以包含换行符`
    fmt.Println("多行字符串:")
    fmt.Println(multiLine)
    
    // 6. 字符串索引和切片
    fmt.Printf("第一个字符: %c\n", str1[0])
    fmt.Printf("前5个字符: %s\n", str1[:5])
    fmt.Printf("从第7个字符开始: %s\n", str1[7:])
    fmt.Printf("中间部分: %s\n", str1[7:9])
    
    // 7. 字符串遍历
    fmt.Println("按字节遍历:")
    for i := 0; i < len(str1); i++ {
        fmt.Printf("%c ", str1[i])
    }
    fmt.Println()
    
    fmt.Println("按字符遍历(处理Unicode):")
    for i, char := range str2 {
        fmt.Printf("索引%d: %c ", i, char)
    }
    fmt.Println()
}

数组类型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package main

import "fmt"

func main() {
    // 1. 数组声明和初始化
    var arr1 [5]int                    // 声明长度为5的int数组,零值初始化
    var arr2 = [5]int{1, 2, 3, 4, 5}  // 声明并初始化
    arr3 := [...]int{10, 20, 30}      // 自动推断长度
    
    fmt.Printf("arr1: %v\n", arr1)
    fmt.Printf("arr2: %v\n", arr2)
    fmt.Printf("arr3: %v\n", arr3)
    
    // 2. 数组长度和访问
    fmt.Printf("arr2长度: %d\n", len(arr2))
    fmt.Printf("arr2第一个元素: %d\n", arr2[0])
    fmt.Printf("arr2最后一个元素: %d\n", arr2[len(arr2)-1])
    
    // 3. 修改数组元素
    arr2[0] = 100
    fmt.Printf("修改后的arr2: %v\n", arr2)
    
    // 4. 数组遍历
    fmt.Println("使用for循环遍历:")
    for i := 0; i < len(arr2); i++ {
        fmt.Printf("arr2[%d] = %d\n", i, arr2[i])
    }
    
    fmt.Println("使用range遍历:")
    for index, value := range arr2 {
        fmt.Printf("索引%d: 值%d\n", index, value)
    }
    
    // 5. 多维数组
    var matrix [3][3]int = [3][3]int{
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9},
    }
    
    fmt.Println("3x3矩阵:")
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            fmt.Printf("%d ", matrix[i][j])
        }
        fmt.Println()
    }
    
    // 6. 数组比较
    arr4 := [3]int{1, 2, 3}
    arr5 := [3]int{1, 2, 3}
    arr6 := [3]int{1, 2, 4}
    
    fmt.Printf("arr4 == arr5: %t\n", arr4 == arr5)
    fmt.Printf("arr4 == arr6: %t\n", arr4 == arr6)
}

切片类型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package main

import "fmt"

func main() {
    // 1. 切片声明和初始化
    var slice1 []int                    // 声明切片,零值为nil
    slice2 := []int{1, 2, 3, 4, 5}     // 声明并初始化
    slice3 := make([]int, 5)           // 使用make创建长度为5的切片
    slice4 := make([]int, 3, 10)       // 长度为3,容量为10的切片
    
    fmt.Printf("slice1: %v, len: %d, cap: %d, nil: %t\n", 
        slice1, len(slice1), cap(slice1), slice1 == nil)
    fmt.Printf("slice2: %v, len: %d, cap: %d\n", 
        slice2, len(slice2), cap(slice2))
    fmt.Printf("slice3: %v, len: %d, cap: %d\n", 
        slice3, len(slice3), cap(slice3))
    fmt.Printf("slice4: %v, len: %d, cap: %d\n", 
        slice4, len(slice4), cap(slice4))
    
    // 2. 从数组创建切片
    arr := [5]int{10, 20, 30, 40, 50}
    slice5 := arr[1:4]  // 从索引1到3(不包括4)
    slice6 := arr[:3]   // 从开始到索引2
    slice7 := arr[2:]   // 从索引2到结束
    slice8 := arr[:]    // 整个数组
    
    fmt.Printf("原数组: %v\n", arr)
    fmt.Printf("slice5 [1:4]: %v\n", slice5)
    fmt.Printf("slice6 [:3]: %v\n", slice6)
    fmt.Printf("slice7 [2:]: %v\n", slice7)
    fmt.Printf("slice8 [:]: %v\n", slice8)
    
    // 3. 切片操作
    // append - 添加元素
    slice2 = append(slice2, 6, 7, 8)
    fmt.Printf("append后: %v, len: %d, cap: %d\n", 
        slice2, len(slice2), cap(slice2))
    
    // copy - 复制切片
    slice9 := make([]int, len(slice2))
    copy(slice9, slice2)
    fmt.Printf("复制的切片: %v\n", slice9)
    
    // 4. 切片的切片
    subSlice := slice2[2:5]
    fmt.Printf("子切片 [2:5]: %v\n", subSlice)
    
    // 修改子切片会影响原切片(共享底层数组)
    subSlice[0] = 999
    fmt.Printf("修改子切片后,原切片: %v\n", slice2)
}

映射类型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package main

import "fmt"

func main() {
    // 1. 映射声明和初始化
    var map1 map[string]int                    // 声明映射,零值为nil
    map2 := map[string]int{                    // 声明并初始化
        "apple":  5,
        "banana": 3,
        "orange": 8,
    }
    map3 := make(map[string]int)               // 使用make创建映射
    
    fmt.Printf("map1: %v, nil: %t\n", map1, map1 == nil)
    fmt.Printf("map2: %v\n", map2)
    fmt.Printf("map3: %v\n", map3)
    
    // 2. 映射操作
    // 添加/修改元素
    map3["go"] = 100
    map3["python"] = 90
    map3["java"] = 85
    
    fmt.Printf("添加元素后的map3: %v\n", map3)
    
    // 获取元素
    value := map3["go"]
    fmt.Printf("go的值: %d\n", value)
    
    // 检查键是否存在
    value, exists := map3["go"]
    fmt.Printf("go存在: %t, 值: %d\n", exists, value)
    
    value, exists = map3["rust"]
    fmt.Printf("rust存在: %t, 值: %d\n", exists, value)
    
    // 删除元素
    delete(map3, "java")
    fmt.Printf("删除java后: %v\n", map3)
    
    // 3. 遍历映射
    fmt.Println("遍历map2:")
    for key, value := range map2 {
        fmt.Printf("%s: %d\n", key, value)
    }
    
    // 只遍历键
    fmt.Println("只遍历键:")
    for key := range map2 {
        fmt.Printf("键: %s\n", key)
    }
    
    // 只遍历值
    fmt.Println("只遍历值:")
    for _, value := range map2 {
        fmt.Printf("值: %d\n", value)
    }
    
    // 4. 映射长度
    fmt.Printf("map2长度: %d\n", len(map2))
    fmt.Printf("map3长度: %d\n", len(map3))
}

结构体类型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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 {
    Person  // 匿名字段(嵌入)
    Address // 匿名字段(嵌入)
    Salary  float64
    Department string
}

func main() {
    // 1. 结构体声明和初始化
    var p1 Person                           // 零值初始化
    p2 := Person{"张三", 25, "北京"}          // 按字段顺序初始化
    p3 := Person{                           // 按字段名初始化
        Name: "李四",
        Age:  30,
        City: "上海",
    }
    
    fmt.Printf("p1: %+v\n", p1)
    fmt.Printf("p2: %+v\n", p2)
    fmt.Printf("p3: %+v\n", p3)
    
    // 2. 访问和修改字段
    fmt.Printf("p2的姓名: %s\n", p2.Name)
    p2.Age = 26
    fmt.Printf("修改年龄后的p2: %+v\n", p2)
    
    // 3. 结构体指针
    p4 := &Person{"王五", 28, "广州"}
    fmt.Printf("p4指针: %p\n", p4)
    fmt.Printf("p4指向的值: %+v\n", *p4)
    
    // 通过指针访问字段(Go会自动解引用)
    fmt.Printf("通过指针访问姓名: %s\n", p4.Name)
    p4.Age = 29
    fmt.Printf("通过指针修改后: %+v\n", *p4)
    
    // 4. 嵌套结构体
    emp := Employee{
        Person: Person{
            Name: "赵六",
            Age:  32,
            City: "深圳",
        },
        Address: Address{
            Street:  "科技园路1号",
            City:    "深圳",
            ZipCode: "518000",
        },
        Salary:     15000.0,
        Department: "技术部",
    }
    
    fmt.Printf("员工信息: %+v\n", emp)
    
    // 访问嵌入字段
    fmt.Printf("员工姓名: %s\n", emp.Name)        // 直接访问嵌入的Person.Name
    fmt.Printf("员工地址: %s\n", emp.Street)      // 直接访问嵌入的Address.Street
    fmt.Printf("员工城市: %s\n", emp.Person.City) // 明确指定Person.City
    
    // 5. 匿名结构体
    point := struct {
        X, Y int
    }{10, 20}
    
    fmt.Printf("匿名结构体: %+v\n", point)
}

接口类型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package main

import "fmt"

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

// 实现接口的结构体
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)
}

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 main() {
    // 1. 接口变量
    var shape Shape
    
    // 接口的零值是nil
    fmt.Printf("接口零值: %v, nil: %t\n", shape, shape == nil)
    
    // 2. 接口赋值
    rect := Rectangle{Width: 10, Height: 5}
    circle := Circle{Radius: 3}
    
    shape = rect
    fmt.Printf("矩形面积: %.2f, 周长: %.2f\n", shape.Area(), shape.Perimeter())
    
    shape = circle
    fmt.Printf("圆形面积: %.2f, 周长: %.2f\n", shape.Area(), shape.Perimeter())
    
    // 3. 空接口
    var empty interface{}
    
    empty = 42
    fmt.Printf("空接口存储int: %v\n", empty)
    
    empty = "Hello"
    fmt.Printf("空接口存储string: %v\n", empty)
    
    empty = rect
    fmt.Printf("空接口存储Rectangle: %v\n", empty)
    
    // 4. 类型断言
    if value, ok := empty.(Rectangle); ok {
        fmt.Printf("类型断言成功,矩形: %+v\n", value)
    }
    
    // 5. 类型选择
    switch v := empty.(type) {
    case int:
        fmt.Printf("这是一个int: %d\n", v)
    case string:
        fmt.Printf("这是一个string: %s\n", v)
    case Rectangle:
        fmt.Printf("这是一个Rectangle: %+v\n", v)
    default:
        fmt.Printf("未知类型: %T\n", v)
    }
}

总结

  1. 基本类型

    • 布尔型:bool
    • 整数型:int8, int16, int32, int64, int, uint8, uint16, uint32, uint64, uint, uintptr
    • 浮点型:float32, float64
    • 复数型:complex64, complex128
    • 字符串:string
  2. 复合类型

    • 数组:固定长度,值类型
    • 切片:动态数组,引用类型
    • 映射:键值对,引用类型
    • 结构体:自定义类型,值类型
  3. 接口类型

    • 定义方法集合
    • 实现多态
    • 空接口可以存储任何类型
  4. 类型特点

    • 静态类型系统
    • 零值初始化
    • 类型安全
    • 支持类型推断
updatedupdated2025-09-202025-09-20